home *** CD-ROM | disk | FTP | other *** search
/ Aminet 43 / Aminet 43 (2001)(GTI - Schatztruhe)[!][Jun 2001].iso / Aminet / comm / mail / YAM22src.lha / YAM_MA.c < prev    next >
C/C++ Source or Header  |  2000-11-03  |  105KB  |  2,242 lines

  1. /***************************************************************************
  2.  
  3.  YAM - Yet Another Mailer
  4.  Copyright (C) 2000  Marcel Beck <mbeck@yam.ch>
  5.  
  6.  This program is free software; you can redistribute it and/or modify
  7.  it under the terms of the GNU General Public License as published by
  8.  the Free Software Foundation; either version 2 of the License, or
  9.  (at your option) any later version.
  10.  
  11.  This program is distributed in the hope that it will be useful,
  12.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  GNU General Public License for more details.
  15.  
  16.  You should have received a copy of the GNU General Public License
  17.  along with this program; if not, write to the Free Software
  18.  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  
  20.  YAM Official Support Site :  http://www.yam.ch
  21.  YAM OpenSource project    :  http://sourceforge.net/projects/yamos/
  22.  
  23. ***************************************************************************/
  24.  
  25. #include "YAM.h"
  26. #include "YAM_rexx.h"
  27.  
  28. /***************************************************************************
  29.  Module: Main
  30. ***************************************************************************/
  31.  
  32. /*** Private functions ***/
  33. /// MA_GetSortType
  34. //  Calculates value for sort indicator
  35. ULONG MA_GetSortType(int sort)
  36. {
  37.    ULONG sort2col[8] = { 0,4,6,1,1,3,5,0 };
  38.    if (sort > 0) return sort2col[abs(sort)];
  39.    else return sort2col[abs(sort)] | MUIV_NList_SortTypeAdd_2Values;
  40. }
  41. ///
  42. /// MA_SetSortFlag
  43. //  Sets sort indicators in message listview header
  44. void MA_SetSortFlag(void)
  45. {
  46.    struct Folder *fo = FO_GetCurrentFolder();
  47.    set(G->MA->GUI.NL_MAILS, MUIA_NList_SortType, MA_GetSortType(fo->Sort[0]));
  48.    set(G->MA->GUI.NL_MAILS, MUIA_NList_SortType2, MA_GetSortType(fo->Sort[1]));
  49. }
  50. ///
  51. /// MA_ChangeTransfer
  52. //  Disables menus and toolbar buttons during transfer operations
  53. void MA_ChangeTransfer(BOOL on)
  54. {
  55.    struct MA_GUIData *gui = &G->MA->GUI;
  56.    if (gui->TO_TOOLBAR) DoMethod(gui->TO_TOOLBAR, MUIM_Toolbar_MultiSet, MUIV_Toolbar_Set_Ghosted, !on, 10,11, -1);
  57.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, on, gui->MI_IMPORT, gui->MI_EXPORT, gui->MI_SENDALL, gui->MI_EXCHANGE, gui->MI_GETMAIL, gui->MI_CSINGLE, NULL);
  58. }
  59. ///
  60. /// MA_ChangeSelectedFunc
  61. //  User selected some message(s) in the message list
  62. SAVEDS void MA_ChangeSelectedFunc(void)
  63. {
  64.    struct MA_GUIData *gui = &G->MA->GUI;
  65.    struct Folder *fo = FO_GetCurrentFolder();
  66.    int selected, type, i;
  67.    BOOL active, hasattach = FALSE, beingedited = FALSE;
  68.    struct Mail *mail;
  69.  
  70.    if (!fo) return;
  71.    type = fo->Type;
  72.    DoMethod(gui->NL_MAILS, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &mail);
  73.    if (active = (mail != NULL)) if (mail->Flags & MFLAG_MULTIPART) hasattach = TRUE;
  74.    for (i = 0; i < MAXWR; i++) if (mail && G->WR[i]) if (G->WR[i]->Mail == mail) beingedited = TRUE;
  75.    if (!mail) if (!GetMUI(gui->NL_MAILS, MUIA_NList_Entries)) set(gui->WI, MUIA_Window_ActiveObject, gui->LV_FOLDERS);
  76.    DoMethod(gui->NL_MAILS, MUIM_NList_Select, MUIV_NList_Select_All, MUIV_NList_Select_Ask, &selected);
  77.    if (gui->TO_TOOLBAR)
  78.    {
  79.       DoMethod(gui->TO_TOOLBAR, MUIM_Toolbar_Set, 1, MUIV_Toolbar_Set_Ghosted, !active || !OUTGOING(type) || beingedited);
  80.       DoMethod(gui->TO_TOOLBAR, MUIM_Toolbar_Set, 0, MUIV_Toolbar_Set_Ghosted, !active);
  81.       DoMethod(gui->TO_TOOLBAR, MUIM_Toolbar_MultiSet, MUIV_Toolbar_Set_Ghosted, !active && !selected, 2,3,4,7,8, -1);
  82.    }
  83.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, active || selected,
  84.       gui->MI_MOVE, gui->MI_DELETE, gui->MI_GETADDRESS, gui->MI_REPLY, gui->MI_FORWARD, gui->MI_STATUS,
  85.       gui->MI_EXPMSG, gui->MI_COPY, gui->MI_PRINT, gui->MI_SAVE, gui->MI_CHSUBJ, NULL);
  86.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, active, gui->MI_READ, gui->MI_BOUNCE, NULL);
  87.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, active && OUTGOING(type) && !beingedited, gui->MI_EDIT, NULL);
  88.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, type == FT_OUTGOING && (active || selected), gui->MI_SEND, gui->MI_TOHOLD, gui->MI_TOQUEUED, NULL);
  89.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, !OUTGOING(type) && (active || selected) , gui->MI_TOREAD, gui->MI_TOUNREAD, NULL);
  90.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, hasattach && (active || selected), gui->MI_ATTACH, gui->MI_SAVEATT, gui->MI_REMATT, NULL);
  91. }
  92. MakeHook(MA_ChangeSelectedHook, MA_ChangeSelectedFunc);
  93. ///
  94. /// MA_SetMessageInfoFunc
  95. //  Builds help bubble for message list
  96. SAVEDS void MA_SetMessageInfoFunc(void)
  97. {
  98.    static char buffer[SIZE_DEFAULT+SIZE_SUBJECT+2*SIZE_REALNAME+2*SIZE_ADDRESS+SIZE_MFILE];
  99.    char *sh = NULL;
  100.    struct Mail *mail = MA_GetActiveMail(NULL, NULL, NULL);   
  101.    if (mail) sprintf(sh = buffer, GetStr(MSG_MA_MessageInfo), mail->From.RealName, mail->From.Address, mail->To.RealName, mail->To.Address, mail->Subject, DateStamp2String(&mail->Date, C->SwatchBeat ? DSS_DATEBEAT : DSS_DATETIME), mail->MailFile, mail->Size);
  102.    set(G->MA->GUI.NL_MAILS, MUIA_ShortHelp, sh);
  103. }
  104. MakeHook(MA_SetMessageInfoHook, MA_SetMessageInfoFunc);
  105. ///
  106. /// MA_SetFolderInfoFunc
  107. //  Builds help bubble for folder list
  108. SAVEDS void MA_SetFolderInfoFunc(void)
  109. {
  110.    static char buffer[SIZE_DEFAULT+SIZE_NAME+SIZE_PATH];
  111.    char *sh = NULL;
  112.    struct Folder *fo = FO_GetCurrentFolder();      
  113.    if (fo->Type != FT_SEPARATOR) sprintf(sh = buffer, GetStr(MSG_MA_FolderInfo), fo->Name, fo->Path, fo->Size, fo->Total, fo->New, fo->Unread);
  114.    set(G->MA->GUI.NL_FOLDERS, MUIA_ShortHelp, sh);
  115. }
  116. MakeHook(MA_SetFolderInfoHook, MA_SetFolderInfoFunc);
  117. ///
  118. /// MA_GetActiveMail
  119. //  Returns pointers to the active message and folder
  120. struct Mail *MA_GetActiveMail(struct Folder *forcefolder, struct Folder **folderp, int *activep)
  121. {
  122.    struct Folder *folder;
  123.    int active;
  124.    struct Mail *mail = NULL;
  125.  
  126.    folder = forcefolder ? forcefolder : FO_GetCurrentFolder();
  127.    MA_GetIndex(folder);
  128.    get(G->MA->GUI.NL_MAILS, MUIA_NList_Active, &active);
  129.    if (active != MUIV_NList_Active_Off) DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_GetEntry, active, &mail);
  130.    if (folderp) *folderp = folder;
  131.    if (activep) *activep = active;
  132.    return mail;
  133. }
  134. ///
  135. /// MA_SetMailStatus
  136. //  Sets the status of a message
  137. void MA_SetMailStatus(struct Mail *mail, int stat)
  138. {
  139.    struct MailInfo *mi;
  140.    char statstr[3];
  141.    int pf;
  142.  
  143.    strcpy(statstr, Status[stat&0xFF]);
  144.    if (pf = ((mail->Flags & 0x0700) >> 8)) sprintf(statstr+1, "%c", pf+'0');
  145.    if (stat != mail->Status)
  146.    {
  147.       mail->Status = stat&0xFF;
  148.       MA_ExpireIndex(mail->Folder);
  149.       mi = GetMailInfo(mail);
  150.       SetComment(mi->FName, statstr);
  151.       if (mi->Display) DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_Redraw, mi->Pos);
  152.    }
  153.    else SetComment(GetMailFile(NULL, NULL, mail), statstr);
  154. }
  155. ///
  156. /// MA_CreateFullList
  157. //  Builds a list containing all messages in a folder
  158. struct Mail **MA_CreateFullList(struct Folder *fo)
  159. {
  160.    int selected = fo->Total;
  161.    struct Mail *mail, **mlist = NULL;
  162.  
  163.    if (selected) if (mlist = calloc(selected+2, sizeof(struct Mail *)))
  164.    {
  165.       mlist[0] = (struct Mail *)selected;
  166.       mlist[1] = (struct Mail *)2;
  167.       for (selected = 2, mail = fo->Messages; mail; selected++, mail = mail->Next)
  168.          mlist[selected] = mail;
  169.    }
  170.    return mlist;
  171. }
  172. ///
  173. /// MA_CreateMarkedList
  174. //  Builds a linked list containing the selected messages
  175. struct Mail **MA_CreateMarkedList(APTR lv)
  176. {
  177.    int id, selected;
  178.    struct Mail *mail, **mlist = NULL;
  179.  
  180.    DoMethod(lv, MUIM_NList_Select, MUIV_NList_Select_All, MUIV_NList_Select_Ask, &selected);
  181.    if (selected)
  182.    {
  183.       if (mlist = calloc(selected+2, sizeof(struct Mail *)))
  184.       {
  185.          mlist[0] = (struct Mail *)selected;
  186.          mlist[1] = (struct Mail *)1;
  187.          for (selected = 2, id = MUIV_NList_NextSelected_Start; ; selected++)
  188.          {
  189.             DoMethod(lv, MUIM_NList_NextSelected, &id);
  190.             if (id == MUIV_NList_NextSelected_End) break;
  191.             DoMethod(lv, MUIM_NList_GetEntry, id, &mail);
  192.             mail->Position = id;
  193.             mlist[selected] = mail;
  194.          }
  195.       }
  196.    }
  197.    else
  198.    {
  199.       DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &mail);
  200.       if (mail) if (mlist = calloc(3, sizeof(struct Mail *)))
  201.       {
  202.          get(G->MA->GUI.NL_MAILS, MUIA_NList_Active, &id);
  203.          mail->Position = id;
  204.          mlist[0] = (struct Mail *)1;
  205.          mlist[2] = mail;
  206.       }
  207.    }
  208.    return mlist;
  209. }
  210. ///
  211. /// MA_DeleteSingle
  212. //  Deletes a single message
  213. void MA_DeleteSingle(struct Mail *mail, BOOL forceatonce)
  214. {
  215.    if (C->RemoveAtOnce || mail->Folder->Type == FT_DELETED || forceatonce)
  216.    {        
  217.       struct MailInfo *mi = GetMailInfo(mail);
  218.       AppendLogVerbose(21, GetStr(MSG_LOG_DeletingVerbose), AddrName(mail->From), mail->Subject, mail->Folder->Name, "");
  219.       DeleteFile(mi->FName);
  220.       if (mi->Display) DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_Remove, mi->Pos);
  221.       RemoveMailFromList(mail);
  222.    }
  223.    else MA_MoveCopy(mail, mail->Folder, FO_GetFolderByType(FT_DELETED, NULL), FALSE);
  224. }
  225. ///
  226. /// MA_MoveCopySingle
  227. //  Moves or copies a single message from one folder to another
  228. struct Mail *MA_MoveCopySingle(struct Mail *mail, int pos, struct Folder *from, struct Folder *to, BOOL copyit)
  229. {
  230.    struct Mail cmail = *mail;
  231.    char mfile[SIZE_MFILE];
  232.    APTR lv;
  233.  
  234.    strcpy(mfile, mail->MailFile);
  235.    if (TransferMailFile(copyit, mail, to))
  236.    {
  237.       strcpy(cmail.MailFile, mail->MailFile);
  238.       if (copyit) AppendLogVerbose(25, GetStr(MSG_LOG_CopyingVerbose), AddrName(mail->From), mail->Subject, from->Name, to->Name);
  239.              else AppendLogVerbose(23, GetStr(MSG_LOG_MovingVerbose),  AddrName(mail->From), mail->Subject, from->Name, to->Name);
  240.       if (copyit) strcpy(mail->MailFile, mfile);
  241.       else
  242.       {
  243.          if (lv = WhichLV(from)) DoMethod(lv, MUIM_NList_Remove, pos);
  244.          RemoveMailFromList(mail);
  245.       }
  246.       mail = AddMailToList(&cmail, to);
  247.       if (lv = WhichLV(to)) DoMethod(lv, MUIM_NList_InsertSingle, mail, MUIV_NList_Insert_Sorted);
  248.       if (mail->Status == STATUS_SNT && to->Type == FT_OUTGOING) MA_SetMailStatus(mail, STATUS_WFS);
  249.       return mail;
  250.    }
  251.    return NULL;
  252. }
  253. ///
  254. /// MA_MoveCopy
  255. //  Moves or copies messages from one folder to another
  256. void MA_MoveCopy(struct Mail *mail, struct Folder *frombox, struct Folder *tobox, BOOL copyit)
  257. {
  258.    APTR lv;
  259.    struct MailInfo *mi;
  260.    struct Mail **mlist;
  261.    int i, pos, selected = 0;
  262.   
  263.    if (frombox == tobox && !copyit) return;
  264.    if (!(lv = WhichLV(frombox)) && !mail) return;
  265.    if (mail)
  266.    {
  267.       selected = 1;
  268.       mi = GetMailInfo(mail);
  269.       MA_MoveCopySingle(mail, mi->Pos, frombox, tobox, copyit);
  270.    }
  271.    else if (mlist = MA_CreateMarkedList(lv))
  272.    {
  273.       selected = (int)*mlist;
  274.       set(lv, MUIA_NList_Quiet, TRUE);
  275.       Busy(GetStr(MSG_BusyMoving), itoa(selected), 0, selected);
  276.       for (i = 0; i < selected; i++)
  277.       {
  278.          Busy(NULL, NULL, i, 0);
  279.          mail = mlist[i+2];
  280.          if (copyit) pos = mail->Position; else { mi = GetMailInfo(mail); pos = mi->Pos; }
  281.          MA_MoveCopySingle(mail, pos, frombox, tobox, copyit);
  282.       }
  283.       BusyEnd;
  284.       set(lv, MUIA_NList_Quiet, FALSE);
  285.       free(mlist);
  286.    }
  287.    if (copyit) AppendLogNormal(24, GetStr(MSG_LOG_Copying), (void *)selected, FolderName(frombox), FolderName(tobox), "");
  288.           else AppendLogNormal(22, GetStr(MSG_LOG_Moving),  (void *)selected, FolderName(frombox), FolderName(tobox), "");
  289.    if (!copyit) DisplayStatistics(frombox);
  290.    DisplayStatistics(tobox);
  291.    MA_ChangeSelectedFunc();
  292. }
  293. ///
  294. /// MA_UpdateStatus
  295. //  Changes status of all new messages to unread
  296. void MA_UpdateStatus(void)
  297. {
  298.    int i;
  299.    struct Mail *mail;
  300.    struct Folder **flist;
  301.  
  302.    if (flist = FO_CreateList())
  303.    {
  304.       for (i = 1; i <= (int)*flist; i++) if (!OUTGOING(flist[i]->Type)) if (flist[i]->LoadedMode == 2)
  305.       {
  306.          BOOL updated = FALSE;
  307.          for (mail = flist[i]->Messages; mail; mail = mail->Next)
  308.             if (mail->Status == STATUS_NEW) { updated = TRUE; MA_SetMailStatus(mail, STATUS_UNR); }
  309.          if (updated) DisplayStatistics(flist[i]);
  310.       }
  311.       free(flist);
  312.    }
  313. }
  314. ///
  315.  
  316. /*** Main button functions ***/
  317. /// MA_ReadMessage
  318. //  Loads active message into a read window
  319. SAVEDS ASM void MA_ReadMessage(REG(a1) int *arg)
  320. {
  321.    static int lastwin = 0;
  322.    struct Mail *mail;
  323.    int i, winnum;
  324.  
  325.    if (mail = MA_GetActiveMail(ANYBOX, NULL, NULL))
  326.    {
  327.       for (i = 0; i < MAXRE; i++) if (G->RE[i]) if (mail == G->RE[i]->MailPtr)
  328.       {
  329.          DoMethod(G->RE[i]->GUI.WI, MUIM_Window_ToFront);
  330.          set(G->RE[i]->GUI.WI, MUIA_Window_Activate, TRUE);
  331.          return;
  332.       }
  333.       if ((winnum = RE_Open(C->MultipleWindows ? -1 : lastwin, TRUE)) != -1)
  334.       {
  335.          lastwin = winnum;
  336.          if (SafeOpenWindow(G->RE[winnum]->GUI.WI)) RE_ReadMessage(winnum, mail);
  337.          else DisposeModulePush(&G->RE[winnum]);
  338.       }
  339.    }
  340. }
  341. MakeHook(MA_ReadMessageHook, MA_ReadMessage);
  342. ///
  343. /// AppendRcpt
  344. //  Appends a recipient address to a string
  345. char *AppendRcpt(char *sbuf, struct Person *pe, BOOL excludeme)
  346. {
  347.    char *ins;
  348.    if (strchr(pe->Address,'@'))
  349.       ins = BuildAddrName2(pe);
  350.    else
  351.    {
  352.       char addr[SIZE_ADDRESS];
  353.       strcpy(addr, pe->Address);
  354.       strcat(addr, strchr(C->EmailAddress, '@'));
  355.       ins = BuildAddrName(addr, pe->RealName);
  356.    }
  357.    if (excludeme) if (!stricmp(pe->Address, C->EmailAddress)) return sbuf;
  358.    if (stristr(sbuf, ins)) return sbuf;
  359.    if (*sbuf) sbuf = StrBufCat(sbuf, ", ");
  360.    return StrBufCat(sbuf, ins);
  361. }
  362. ///
  363. /// MA_CmpDate
  364. //  Compares two messages by date
  365. int MA_CmpDate(struct Mail **pentry1, struct Mail **pentry2)
  366. {
  367.    return CompareDates(&(pentry2[0]->Date), &(pentry1[0]->Date));
  368. }
  369. ///
  370. /// MA_InsertIntroText
  371. //  Inserts a phrase into the message text
  372. void MA_InsertIntroText(FILE *fh, char *text, struct ExpandTextData *etd)
  373. {
  374.    if (*text)
  375.    {
  376.       char *sbuf;
  377.       sbuf = ExpandText(text, etd);
  378.       fprintf(fh, "%s\n", sbuf);
  379.       FreeStrBuf(sbuf);
  380.    }
  381. }
  382. ///
  383. /// MA_EditorNotification
  384. //  Starts file notification for temporary message file
  385. void MA_EditorNotification(int winnum)
  386. {
  387.    FileToEditor(G->WR_Filename[winnum], G->WR[winnum]->GUI.TE_EDIT);
  388.    StartNotify(&G->WR_NRequest[winnum]);
  389.    set(G->WR[winnum]->GUI.TE_EDIT, MUIA_TextEditor_HasChanged, FALSE);
  390. }
  391. ///
  392. /// MA_SetupQuoteString
  393. //  Creates quote string by replacing variables with values
  394. void MA_SetupQuoteString(struct WR_ClassData *wr, struct ExpandTextData *etd, struct Mail *mail)
  395. {
  396.    struct ExpandTextData l_etd;
  397.    char *sbuf;
  398.    if (!etd) etd = &l_etd;
  399.    etd->OS_Name      = mail ? (*(mail->From.RealName) ? mail->From.RealName : mail->From.Address) : "";
  400.    etd->OS_Address   = mail ? mail->From.Address : "";
  401.    etd->OM_Subject   = mail ? mail->Subject : "";
  402.    etd->OM_Date      = mail ? &(mail->Date) : &(G->StartDate);
  403.    etd->R_Name       = "";
  404.    etd->R_Address    = "";
  405.    sbuf = ExpandText(C->QuoteText, etd);
  406.    stccpy(wr->QuoteText, TrimEnd(sbuf), SIZE_DEFAULT);
  407.    FreeStrBuf(sbuf);
  408. }
  409. ///
  410. /// MA_CheckWriteWindow
  411. //  Opens a write window
  412. int MA_CheckWriteWindow(int winnum)
  413. {
  414.    if (SafeOpenWindow(G->WR[winnum]->GUI.WI)) return winnum;
  415.    WR_Cleanup(winnum);
  416.    DisposeModulePush(&G->WR[winnum]);
  417.    return -1;
  418. }
  419. ///
  420. /// MA_NewNew
  421. //  Creates a new, empty message
  422. int MA_NewNew(struct Mail *mail, int flags)
  423. {
  424.    BOOL quiet = flags & NEWF_QUIET;
  425.    struct Folder *folder = FO_GetCurrentFolder();
  426.    int winnum = -1;
  427.    struct WR_ClassData *wr;
  428.    FILE *out;
  429.  
  430.    if (CO_IsValid()) if ((winnum = WR_Open(quiet ? 2 : -1, FALSE)) >= 0)
  431.    {
  432.       if (out = fopen(G->WR_Filename[winnum], "w"))
  433.       {
  434.          wr = G->WR[winnum];
  435.          wr->Mode = NEW_NEW;
  436.          wr->Mail = mail;
  437.          if (mail) setstring(wr->GUI.ST_TO, BuildAddrName2(GetReturnAddress(mail)));
  438.          else if (folder) if (folder->MLAddress[0] && folder->Type != FT_INCOMING) setstring(wr->GUI.ST_TO, folder->MLAddress);
  439.          MA_SetupQuoteString(wr, NULL, NULL);
  440.          MA_InsertIntroText(out, C->NewIntro, NULL);
  441.          MA_InsertIntroText(out, C->Greetings, NULL);
  442.          fclose(out);
  443.          WR_AddSignature(G->WR_Filename[winnum], -1);
  444.          if (!quiet) set(wr->GUI.WI, MUIA_Window_Open, TRUE);
  445.          MA_EditorNotification(winnum);
  446.          set(wr->GUI.WI, MUIA_Window_ActiveObject, wr->GUI.ST_TO);
  447.          if (C->LaunchAlways && !quiet) DoMethod(G->App, MUIM_CallHook, &WR_EditHook, winnum);
  448.       } else DisposeModulePush(&G->WR[winnum]);
  449.    }
  450.    if (winnum >= 0 && !quiet) return MA_CheckWriteWindow(winnum);
  451.    return winnum;
  452. }
  453. ///
  454. /// MA_NewEdit
  455. //  Edits a message
  456. int MA_NewEdit(struct Mail *mail, int flags)
  457. {
  458.    BOOL quiet = flags & NEWF_QUIET;
  459.    int i, winnum = -1;
  460.    struct Folder *folder;
  461.    struct WR_ClassData *wr;
  462.    struct ExtendedMail *email;
  463.    FILE *out;
  464.    char *cmsg, *sbuf;
  465.  
  466.    for (i = 0; i < MAXWR; i++) if (G->WR[i]) if (G->WR[i]->Mail == mail) { DoMethod(G->WR[i]->GUI.WI, MUIM_Window_ToFront); return -1; }
  467.    if (CO_IsValid()) if ((winnum = WR_Open(quiet ? 2 : -1, FALSE)) >= 0)
  468.    {
  469.       if (out = fopen(G->WR_Filename[winnum], "w"))
  470.       {
  471.          wr = G->WR[winnum];
  472.          wr->Mode = NEW_EDIT;
  473.          wr->Mail = mail;
  474.          folder = mail->Folder;
  475.          email = MA_ExamineMail(folder, mail->MailFile, NULL, TRUE);
  476.          MA_SetupQuoteString(wr, NULL, mail);
  477.          RE_InitPrivateRC(mail, PM_ALL);
  478.          cmsg = RE_ReadInMessage(4, RIM_EDIT);
  479.          fputs(cmsg, out);
  480.          free(cmsg);
  481.          strcpy(wr->MsgID, email->IRTMsgID);
  482.          setstring(wr->GUI.ST_SUBJECT, mail->Subject);
  483.          setstring(wr->GUI.ST_FROM, BuildAddrName2(&mail->From));
  484.          setstring(wr->GUI.ST_REPLYTO, BuildAddrName2(&mail->ReplyTo));
  485.          sbuf = StrBufCpy(NULL, BuildAddrName2(&mail->To));
  486.          if (mail->Flags & MFLAG_MULTIRCPT)
  487.          {
  488.             *sbuf = 0;
  489.             sbuf = AppendRcpt(sbuf, &mail->To, FALSE);
  490.             for (i = 0; i < email->NoSTo; i++) sbuf = AppendRcpt(sbuf, &email->STo[i], FALSE);
  491.             setstring(wr->GUI.ST_TO, sbuf);
  492.             *sbuf = 0;
  493.             for (i = 0; i < email->NoCC; i++) sbuf = AppendRcpt(sbuf, &email->CC[i], FALSE);
  494.             setstring(wr->GUI.ST_CC, sbuf);
  495.             *sbuf = 0;
  496.             for (i = 0; i < email->NoBCC; i++) sbuf = AppendRcpt(sbuf, &email->BCC[i], FALSE);
  497.             setstring(wr->GUI.ST_BCC, sbuf);
  498.          }
  499.          else setstring(wr->GUI.ST_TO, sbuf);
  500.          FreeStrBuf(sbuf);
  501.          if (email->Headers) setstring(wr->GUI.ST_EXTHEADER, email->Headers);
  502.          setcheckmark(wr->GUI.CH_DELSEND, email->DelSend);
  503.          setcheckmark(wr->GUI.CH_RECEIPT, email->RetRcpt);
  504.          setcheckmark(wr->GUI.CH_DISPNOTI, email->ReceiptType == RCPT_TYPE_ALL);
  505.          setcheckmark(wr->GUI.CH_ADDINFO, (mail->Flags&MFLAG_SENDERINFO) == MFLAG_SENDERINFO);
  506.          setcycle(wr->GUI.CY_IMPORTANCE, 1-mail->Importance);
  507.          setmutex(wr->GUI.RA_SIGNATURE, email->Signature);
  508.          setmutex(wr->GUI.RA_SECURITY, wr->OldSecurity = email->Security);
  509.          if (folder->Type != FT_OUTGOING) DoMethod(G->App, MUIM_MultiSet, MUIA_Disabled, TRUE, wr->GUI.BT_SEND, wr->GUI.BT_HOLD, NULL);
  510.          WR_SetupOldMail(winnum);
  511.          RE_FreePrivateRC();
  512.          fclose(out);
  513.          MA_FreeEMailStruct(email);
  514.          if (!quiet) set(wr->GUI.WI, MUIA_Window_Open, TRUE);
  515.          MA_EditorNotification(winnum);
  516.          sbuf = GetMUIStringPtr(wr->GUI.ST_TO);
  517.          set(wr->GUI.WI, MUIA_Window_ActiveObject, *sbuf ? wr->GUI.TE_EDIT : wr->GUI.ST_TO);
  518.          if (C->LaunchAlways && !quiet) DoMethod(G->App, MUIM_CallHook, &WR_EditHook, winnum);
  519.       } else DisposeModulePush(&G->WR[winnum]);
  520.    }
  521.    if (winnum >= 0 && !quiet) return MA_CheckWriteWindow(winnum);
  522.    return winnum;
  523. }
  524. ///
  525. /// MA_NewBounce
  526. //  Bounces a message
  527. int MA_NewBounce(struct Mail *mail, int flags)
  528. {
  529.    BOOL quiet = flags & NEWF_QUIET;
  530.    int winnum = -1;
  531.    struct WR_ClassData *wr;
  532.  
  533.    if (CO_IsValid()) if ((winnum = WR_Open(quiet ? 2 : -1, TRUE)) >= 0)
  534.    {
  535.       wr = G->WR[winnum];
  536.       wr->Mode = NEW_BOUNCE;
  537.       wr->Mail = mail;
  538.       if (!quiet) set(wr->GUI.WI, MUIA_Window_Open, TRUE);
  539.       set(wr->GUI.WI, MUIA_Window_ActiveObject, wr->GUI.ST_TO);
  540.    }
  541.    if (winnum >= 0 && !quiet) return MA_CheckWriteWindow(winnum);
  542.    return winnum;
  543. }
  544. ///
  545. /// MA_NewForward
  546. //  Forwards a list of messages
  547. int MA_NewForward(struct Mail **mlist, int flags)
  548. {
  549.    BOOL quiet = flags & NEWF_QUIET;
  550.    char buffer[SIZE_LARGE];
  551.    int i, winnum = -1, mlen = (2+(int)mlist[0])*sizeof(struct Mail *);
  552.    struct WR_ClassData *wr;
  553.    struct Mail *mail;
  554.    struct ExtendedMail *email;
  555.    struct ExpandTextData etd;
  556.    FILE *out;
  557.    char *cmsg, *rsub;
  558.  
  559.    if (CO_IsValid()) if ((winnum = WR_Open(quiet ? 2 : -1, FALSE)) >= 0)
  560.    {
  561.       if (out = fopen(G->WR_Filename[winnum], "w"))
  562.       {
  563.          wr = G->WR[winnum];
  564.          wr->Mode = NEW_FORWARD;
  565.          wr->MList = memcpy(malloc(mlen), mlist, mlen);
  566.          rsub = AllocStrBuf(SIZE_SUBJECT);
  567.          qsort(&mlist[2], (int)mlist[0], sizeof(struct Mail *), MA_CmpDate);
  568.          MA_InsertIntroText(out, C->NewIntro, NULL);
  569.          for (i = 0; i < (int)mlist[0]; i++)
  570.          {
  571.             mail = mlist[i+2];
  572.             email = MA_ExamineMail(mail->Folder, mail->MailFile, NULL, TRUE);
  573.             MA_SetupQuoteString(wr, &etd, mail);
  574.             etd.OM_MessageID = email->MsgID;
  575.             etd.R_Name = *mail->To.RealName ? mail->To.RealName : mail->To.Address;
  576.             etd.R_Address = mail->To.Address;
  577.             if (*mail->Subject)
  578.             {
  579.                sprintf(buffer, "%s (fwd)", mail->Subject);
  580.                if (!strstr(rsub, buffer))
  581.                {
  582.                   if (*rsub) rsub = StrBufCat(rsub, "; ");
  583.                   rsub = StrBufCat(rsub, buffer);
  584.                }
  585.             }
  586.             RE_InitPrivateRC(mail, PM_ALL);
  587.             etd.HeaderFile = G->RE[4]->FirstPart->Filename;
  588.             MA_InsertIntroText(out, C->ForwardIntro, &etd);
  589.             MA_FreeEMailStruct(email);
  590.             cmsg = RE_ReadInMessage(4, RIM_EDIT);
  591.             fputs(cmsg, out);
  592.             free(cmsg);
  593.             MA_InsertIntroText(out, C->ForwardFinish, &etd);
  594.             if (!(flags & NEWF_FWD_NOATTACH)) WR_SetupOldMail(winnum);
  595.             RE_FreePrivateRC();
  596.          }
  597.          MA_InsertIntroText(out, C->Greetings, NULL);
  598.          fclose(out);
  599.          WR_AddSignature(G->WR_Filename[winnum], -1);
  600.          setstring(wr->GUI.ST_SUBJECT, rsub);
  601.          FreeStrBuf(rsub);
  602.          if (!quiet) set(wr->GUI.WI, MUIA_Window_Open, TRUE);
  603.          MA_EditorNotification(winnum);
  604.          set(wr->GUI.WI, MUIA_Window_ActiveObject, wr->GUI.ST_TO);
  605.          if (C->LaunchAlways && !quiet) DoMethod(G->App, MUIM_CallHook, &WR_EditHook, winnum);
  606.       } else DisposeModulePush(&G->WR[winnum]);
  607.    }
  608.    if (winnum >= 0 && !quiet) return MA_CheckWriteWindow(winnum);
  609.    return winnum;
  610. }
  611. ///
  612. /// MA_NewReply
  613. //  Creates a reply to a list of messages
  614. int MA_NewReply(struct Mail **mlist, int flags)
  615. {
  616.    int j, i, repmode = 1, winnum = -1, mlen = (2+(int)mlist[0])*sizeof(struct Mail *);
  617.    BOOL doabort = FALSE, multi = (int)mlist[0] > 1, altpat = FALSE, quiet = flags & NEWF_QUIET;
  618.    struct WR_ClassData *wr;
  619.    struct Mail *mail;
  620.    struct ExtendedMail *email;
  621.    struct ExpandTextData etd;
  622.    struct Person *repto, rtml;
  623.    struct Folder **flist, *folder;
  624.    FILE *out;
  625.    char *mlistad = NULL, buffer[SIZE_LARGE];
  626.    char *cmsg, *rto = NULL, *rcc = NULL, *rsub = NULL, *domain, *tofld;
  627.  
  628.    if (CO_IsValid()) if ((winnum = WR_Open(quiet ? 2 : -1, FALSE)) >= 0)
  629.    {
  630.       if (out = fopen(G->WR_Filename[winnum], "w"))
  631.       {
  632.          wr = G->WR[winnum];
  633.          wr->Mode = NEW_REPLY;
  634.          wr->MList = memcpy(malloc(mlen), mlist, mlen);
  635.          rto = AllocStrBuf(SIZE_ADDRESS);
  636.          rcc = AllocStrBuf(SIZE_ADDRESS);
  637.          rsub = AllocStrBuf(SIZE_SUBJECT);
  638.          qsort(&mlist[2], (int)mlist[0], sizeof(struct Mail *), MA_CmpDate);
  639.          for (j = 0; j < (int)mlist[0]; j++)
  640.          {
  641.             mail = mlist[j+2];
  642.             folder = mail->Folder;
  643.             email = MA_ExamineMail(folder, mail->MailFile, NULL, TRUE);
  644.             MA_SetupQuoteString(wr, &etd, mail);
  645.             etd.OM_MessageID = email->MsgID;
  646.             if (*mail->Subject)
  647.             {
  648.                if (j) strcpy(buffer, mail->Subject); else sprintf(buffer, "Re: %s", MA_GetRealSubject(mail->Subject));
  649.                if (!strstr(rsub, buffer))
  650.                {
  651.                   if (*rsub) rsub = StrBufCat(rsub, "; ");
  652.                   rsub = StrBufCat(rsub, buffer);
  653.                }
  654.             }
  655.             if (!multi) strcpy(wr->MsgID, email->MsgID);
  656.             tofld = BuildAddrName2(&mail->To);
  657.             if (folder)
  658.             {
  659.                if (folder->Type == FT_INCOMING)
  660.                {
  661.                   if (flist = FO_CreateList())
  662.                   {
  663.                      for (i = 1; i <= (int)*flist; i++) if (flist[i]->MLPattern[0]) if (MatchNoCase(tofld, flist[i]->MLPattern)) { mlistad = flist[i]->MLAddress[0] ? flist[i]->MLAddress : tofld; break; }
  664.                      free(flist);
  665.                   }
  666.                }
  667.                else if (folder->MLPattern[0]) if (MatchNoCase(tofld, folder->MLPattern)) mlistad = folder->MLAddress[0] ? folder->MLAddress : tofld;
  668.             }
  669.             if (mlistad && !(flags & (NEWF_REP_PRIVATE|NEWF_REP_MLIST)))
  670.             {
  671.                ExtractAddress(mlistad, repto=&rtml);
  672.                if (!strstr(rto, mlistad))
  673.                {
  674.                   if (*rto) rto = StrBufCat(rto, ", ");
  675.                   rto = StrBufCat(rto, mlistad);
  676.                }
  677.                goto cont_repl;
  678.             }
  679.             if (mail->Flags & MFLAG_MULTIRCPT)
  680.                if (!(repmode = MUI_Request(G->App, G->MA->GUI.WI, 0, NULL, GetStr(MSG_MA_ReplyReqOpt), GetStr(MSG_MA_ReplyReq))))
  681.                { MA_FreeEMailStruct(email); fclose(out); doabort = TRUE; goto abort_repl; }
  682.             repto = GetReturnAddress(mail);
  683.             if (repmode == 1)
  684.             {
  685.                if (flags & NEWF_REP_PRIVATE) repto = &mail->From;
  686.                else if (flags & NEWF_REP_MLIST);
  687.                else if (C->CompareAddress && *mail->ReplyTo.Address) if (stricmp(mail->From.Address, mail->ReplyTo.Address))
  688.                {
  689.                   sprintf(buffer, GetStr(MSG_MA_CompareReq), mail->From.Address, mail->ReplyTo.Address);
  690.                   switch (MUI_Request(G->App, G->MA->GUI.WI, 0, NULL, GetStr(MSG_MA_Compare3ReqOpt), buffer))
  691.                   {
  692.                      case 3: rcc = AppendRcpt(rcc, &mail->From, FALSE);
  693.                      case 2: repto = &mail->ReplyTo; break;
  694.                      case 1: repto = &mail->From; break;
  695.                      case 0: MA_FreeEMailStruct(email); doabort = TRUE; fclose(out); goto abort_repl;
  696.                   }
  697.                }
  698.                rto = AppendRcpt(rto, repto, FALSE);
  699.             }
  700.             else
  701.             {
  702.                if (repmode == 2) rto = AppendRcpt(rto, GetReturnAddress(mail), FALSE);
  703.                rto = AppendRcpt(rto, &mail->To, TRUE);
  704.                for (i = 0; i < email->NoSTo; i++) rto = AppendRcpt(rto, &email->STo[i], TRUE);
  705.                for (i = 0; i < email->NoCC; i++) rcc = AppendRcpt(rcc, &email->CC[i], TRUE);
  706.             }
  707. cont_repl:  etd.R_Name = repto->RealName;
  708.             etd.R_Address = repto->Address;
  709.             altpat = FALSE;
  710.             if (!(domain = strchr(repto->Address,'@'))) domain = strchr(C->EmailAddress,'@');
  711.             if (*C->AltReplyPattern) if (MatchNoCase(domain, C->AltReplyPattern)) altpat = TRUE;
  712.             if (!j) MA_InsertIntroText(out, mlistad ? C->MLReplyHello : (altpat ? C->AltReplyHello : C->ReplyHello), &etd);
  713.             if (C->QuoteMessage && !(flags & NEWF_REP_NOQUOTE))
  714.             {
  715.                if (j) fputs("\n", out);
  716.                RE_InitPrivateRC(mail, PM_TEXTS);
  717.                etd.HeaderFile = G->RE[4]->FirstPart->Filename;
  718.                MA_InsertIntroText(out, mlistad ? C->MLReplyIntro : (altpat ? C->AltReplyIntro : C->ReplyIntro), &etd);
  719.                cmsg = RE_ReadInMessage(4, RIM_QUOTE);
  720.                QuoteWordWrap(cmsg, C->EdWrapMode ? C->EdWrapCol-strlen(wr->QuoteText)-1 : 1024, NULL, wr->QuoteText, out);
  721.                free(cmsg);
  722.                RE_FreePrivateRC();
  723.             }
  724.             MA_FreeEMailStruct(email);
  725.          }
  726.          MA_InsertIntroText(out, mlistad ? C->MLReplyBye : (altpat ? C->AltReplyBye: C->ReplyBye), &etd);
  727.          fclose(out);
  728.          WR_AddSignature(G->WR_Filename[winnum], -1);
  729.          setstring(wr->GUI.ST_TO, rto);
  730.          setstring(*rto ? wr->GUI.ST_CC : wr->GUI.ST_TO, rcc);
  731.          setstring(wr->GUI.ST_SUBJECT, rsub);
  732.          if (!quiet) set(wr->GUI.WI, MUIA_Window_Open, TRUE);
  733.          MA_EditorNotification(winnum);
  734.          set(wr->GUI.WI, MUIA_Window_ActiveObject, wr->GUI.TE_EDIT);
  735.          if (C->LaunchAlways && !quiet) DoMethod(G->App, MUIM_CallHook, &WR_EditHook, winnum);
  736.       } else doabort = TRUE;
  737.   }
  738.    if (winnum >= 0 && !quiet) return MA_CheckWriteWindow(winnum);
  739. abort_repl:
  740.    if (doabort) DisposeModulePush(&G->WR[winnum]);
  741.    FreeStrBuf(rto);
  742.    FreeStrBuf(rcc);
  743.    FreeStrBuf(rsub);
  744.    return winnum;
  745. }
  746. ///
  747. /// MA_RemoveAttach
  748. //  Removes attachments from a message
  749. void MA_RemoveAttach(struct Mail *mail)
  750. {
  751.    struct Part *part;
  752.    int f;
  753.    FILE *out, *in;
  754.    char *cmsg, buf[SIZE_LINE], fname[SIZE_PATHFILE], tfname[SIZE_PATHFILE];
  755.    struct Folder *fo = mail->Folder;
  756.  
  757.    sprintf(tfname, "%s.tmp", GetMailFile(fname, NULL, mail));
  758.    RE_InitPrivateRC(mail, PM_ALL);
  759.    cmsg = RE_ReadInMessage(4, RIM_QUIET);
  760.    if (part = G->RE[4]->FirstPart->Next) if (part->Next)
  761.       if (out = fopen(tfname, "w"))
  762.       {
  763.          if (in = fopen(G->RE[4]->FirstPart->Filename, "r"))
  764.          {
  765.             BOOL infield = FALSE, inbody = FALSE;
  766.             while (fgets(buf, SIZE_LINE, in))
  767.             {
  768.                if (!ISpace(*buf)) infield = !strnicmp(buf, "content-transfer-encoding", 25) || !strnicmp(buf, "content-type", 12);
  769.                if (!infield || inbody) fputs(buf, out);
  770.             }
  771.             fclose(in);
  772.          }
  773.          fputs("Content-Transfer-Encoding: 8bit\nContent-Type: text/plain; charset=iso-8859-1\n\n", out);
  774.          fputs(cmsg, out);
  775.          MA_ExpireIndex(mail->Folder);
  776.          fputs(GetStr(MSG_MA_AttachRemoved), out);
  777.          for (part = part->Next; part; part = part->Next)
  778.             fprintf(out, "%s (%ld %s, %s)\n", part->Name ? part->Name : GetStr(MSG_Unnamed), part->Size, GetStr(MSG_Bytes), part->ContentType);
  779.          fclose(out);
  780.          f = FileSize(tfname); fo->Size += f - mail->Size; mail->Size = f;
  781.          mail->Flags &= ~MFLAG_MULTIPART;
  782.          DeleteFile(fname);
  783.          if (fo->XPKType > 1) DoPack(tfname, fname, mail->Folder);
  784.          else RenameFile(tfname, fname);
  785.          MA_SetMailStatus(mail, mail->Status);
  786.          AppendLog(81, GetStr(MSG_LOG_CroppingAtt), mail->MailFile, mail->Folder->Name, "", "");
  787.       }
  788.    free(cmsg);
  789.    RE_FreePrivateRC();
  790. }
  791. ///
  792. /// MA_RemoveAttachFunc
  793. //  Removes attachments from selected messages
  794. SAVEDS void MA_RemoveAttachFunc(void)
  795. {
  796.    struct Mail **mlist;
  797.    int i;
  798.  
  799.    if (mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS))
  800.    {
  801.       int selected = (int)*mlist;
  802.       Busy(GetStr(MSG_BusyRemovingAtt), "", 0, selected);
  803.       for (i = 0; i < selected; i++)
  804.       {
  805.          Busy(NULL, NULL, i, 0);
  806.          MA_RemoveAttach(mlist[i+2]);
  807.       }
  808.       DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_Redraw, MUIV_NList_Redraw_All);
  809.       MA_ChangeSelectedFunc();
  810.       DisplayStatistics(0);
  811.       BusyEnd;
  812.    }
  813. }
  814. MakeHook(MA_RemoveAttachHook, MA_RemoveAttachFunc);
  815. ///
  816. /// MA_SaveAttachFunc
  817. //  Saves all attachments of selected messages to disk
  818. SAVEDS void MA_SaveAttachFunc(void)
  819. {
  820.    struct Mail **mlist, *mail;
  821.    struct Part *part;
  822.    char *cmsg;
  823.    int i;
  824.  
  825.    if (mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS))
  826.    {
  827.       if (ReqFile(ASL_DETACH, G->MA->GUI.WI, GetStr(MSG_RE_SaveMessage), 5, C->DetachDir, ""))
  828.          for (i = 0; i < (int)*mlist; i++)
  829.          {
  830.             RE_InitPrivateRC(mail = mlist[i+2], PM_ALL);
  831.             if (cmsg = RE_ReadInMessage(4, RIM_QUIET))
  832.             {
  833.                free(cmsg);
  834.                if (part = G->RE[4]->FirstPart->Next) if (part->Next)
  835.                   RE_SaveAll(4, G->ASLReq[ASL_DETACH]->fr_Drawer);
  836.             }
  837.             RE_FreePrivateRC();
  838.          }
  839.       free(mlist);
  840.    }
  841. }
  842. MakeHook(MA_SaveAttachHook, MA_SaveAttachFunc);
  843. ///
  844. /// MA_SavePrintFunc
  845. //  Prints selected messages
  846. SAVEDS ASM void MA_SavePrintFunc(REG(a1) int *arg)
  847. {
  848.    BOOL doprint = *arg != 0;
  849.    struct TempFile *tf;
  850.    struct Mail **mlist;
  851.    char *cmsg;
  852.    int i;
  853.  
  854.    if (doprint && C->PrinterCheck) if (!CheckPrinter()) return;
  855.    if (mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS))
  856.    {
  857.       for (i = 0; i < (int)*mlist; i++)
  858.       {
  859.          RE_InitPrivateRC(mlist[i+2], PM_TEXTS);
  860.          if (cmsg = RE_ReadInMessage(4, RIM_READ))
  861.          {
  862.             if (tf = OpenTempFile("w"))
  863.             {
  864.                fputs(cmsg, tf->FP);
  865.                fclose(tf->FP); tf->FP = NULL;
  866.                if (doprint) CopyFile("PRT:", 0, tf->Filename, 0);
  867.                else RE_Export(4, tf->Filename, "", "", 0, FALSE, FALSE, ContType[CT_TX_PLAIN]);
  868.                CloseTempFile(tf);
  869.             }
  870.             free(cmsg);
  871.          }
  872.          RE_FreePrivateRC();
  873.       }
  874.       free(mlist);
  875.    }
  876. }
  877. MakeHook(MA_SavePrintHook, MA_SavePrintFunc);
  878. ///
  879. /// MA_NewMessage
  880. //  Starts a new message
  881. int MA_NewMessage(int mode, int flags)
  882. {
  883.    struct Mail *mail, **mlist = NULL;
  884.    int winnr = -1;
  885.    switch (mode)
  886.    {
  887.       case NEW_NEW:     winnr = MA_NewNew(NULL, flags);
  888.                         break;
  889.       case NEW_EDIT:    if (mail = MA_GetActiveMail(ANYBOX, NULL, NULL)) winnr = MA_NewEdit(mail, flags);
  890.                         break;
  891.       case NEW_BOUNCE:  if (mail = MA_GetActiveMail(ANYBOX, NULL, NULL)) winnr = MA_NewBounce(mail, flags);
  892.                         break;
  893.       case NEW_FORWARD: if (mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS)) winnr = MA_NewForward(mlist, flags);
  894.                         break;
  895.       case NEW_REPLY:   if (mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS)) winnr = MA_NewReply(mlist, flags);
  896.                         break;
  897.    }
  898.    if (mlist) free(mlist);
  899.    return winnr;
  900. }
  901. SAVEDS ASM void MA_NewMessageFunc(REG(a1) int *arg)
  902. {
  903.    int mode = arg[0], flags = 0;
  904.    ULONG qual = arg[1];
  905.    if (arg[2]) return; // Toolbar qualifier bug work-around
  906.    if (mode == NEW_FORWARD && qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) mode = NEW_BOUNCE;
  907.    if (mode == NEW_FORWARD && qual & IEQUALIFIER_CONTROL) flags = NEWF_FWD_NOATTACH;
  908.    if (mode == NEW_REPLY && qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) flags = NEWF_REP_PRIVATE;
  909.    if (mode == NEW_REPLY && qual & (IEQUALIFIER_LALT|IEQUALIFIER_RALT)) flags = NEWF_REP_MLIST;
  910.    if (mode == NEW_REPLY && qual & IEQUALIFIER_CONTROL) flags = NEWF_REP_NOQUOTE;
  911.    MA_NewMessage(mode, flags);
  912. }
  913. MakeHook(MA_NewMessageHook, MA_NewMessageFunc);
  914. ///
  915. /// MA_DeleteMessage
  916. //  Deletes selected messages
  917. void MA_DeleteMessage(BOOL delatonce, BOOL force)
  918. {
  919.    struct Mail **mlist, *mail;
  920.    int i, selected;
  921.    APTR lv = G->MA->GUI.NL_MAILS;
  922.    char buffer[SIZE_DEFAULT];
  923.    struct Folder *delfolder = FO_GetFolderByType(FT_DELETED, NULL), *folder = FO_GetCurrentFolder();
  924.  
  925.    if (!(mlist = MA_CreateMarkedList(lv))) return;
  926.    selected = (int)*mlist;
  927.    if (C->Confirm && selected >= C->ConfirmDelete && !force)
  928.    {
  929.       sprintf(buffer, selected==1 ? GetStr(MSG_MA_1Selected) : GetStr(MSG_MA_xSelected), selected);
  930.       strcat(buffer, GetStr(MSG_MA_ConfirmDel));
  931.       if (!MUI_Request(G->App, G->MA->GUI.WI, 0, GetStr(MSG_MA_ConfirmReq), GetStr(MSG_OkayCancelReq), buffer))
  932.       {
  933.          free(mlist);
  934.          return;
  935.       }
  936.    }
  937.    set(lv, MUIA_NList_Quiet, TRUE);
  938.    Busy(GetStr(MSG_BusyDeleting), itoa(selected), 0, selected);
  939.    if (C->RemoveAtOnce || folder == delfolder) delatonce = TRUE;
  940.    for (i = 0; i < selected; i++)
  941.    {
  942.       Busy(NULL, NULL, i, 0);
  943.       mail = mlist[i+2];
  944.       if (mail->Flags & MFLAG_SENDMDN) if (mail->Status == STATUS_NEW || mail->Status == STATUS_UNR) RE_DoMDN(MDN_DELE, mail);
  945.       if (delatonce) MA_DeleteSingle(mail, TRUE);
  946.       else
  947.       {
  948.          struct MailInfo *mi = GetMailInfo(mail);
  949.          MA_MoveCopySingle(mail, mi->Pos, mail->Folder, delfolder, FALSE);
  950.       }
  951.    }
  952.    BusyEnd;
  953.    set(lv, MUIA_NList_Quiet, FALSE);
  954.    free(mlist);
  955.    if (delatonce)
  956.       AppendLogNormal(20, GetStr(MSG_LOG_Deleting), (void *)selected, folder->Name, "", "");
  957.    else
  958.    {
  959.       AppendLogNormal(22, GetStr(MSG_LOG_Moving), (void *)selected, folder->Name, delfolder->Name, "");
  960.       DisplayStatistics(delfolder);
  961.    }
  962.    DisplayStatistics(NULL);
  963.    MA_ChangeSelectedFunc();
  964. }
  965. SAVEDS ASM void MA_DeleteMessageFunc(REG(a1) int *arg)
  966. {
  967.    BOOL delatonce = arg[0] & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT);
  968.    if (arg[1]) return; // Toolbar qualifier bug work-around
  969.    MA_DeleteMessage(delatonce, FALSE);
  970. }
  971. MakeHook(MA_DeleteMessageHook, MA_DeleteMessageFunc);
  972. ///
  973. /// MA_DelKey
  974. //  User pressed DEL key
  975. SAVEDS ASM void MA_DelKeyFunc(REG(a1) int *arg)
  976. {
  977.    APTR obj;
  978.    get(G->MA->GUI.WI, MUIA_Window_ActiveObject, &obj);
  979.    if (!obj || obj == MUIV_Window_ActiveObject_None) get(G->MA->GUI.WI, MUIA_Window_DefaultObject, &obj);
  980.    if (obj == G->MA->GUI.LV_FOLDERS) FO_DeleteFolderFunc();
  981.    else MA_DeleteMessage(arg[0], FALSE);
  982. }
  983. MakeHook(MA_DelKeyHook, MA_DelKeyFunc);
  984. ///
  985. /// MA_GetAddressSelect
  986. //  Asks user which address (from/replyto) to store
  987. struct Person *MA_GetAddressSelect(struct Mail *mail)
  988. {
  989.    struct Person *pe = GetReturnAddress(mail);
  990.    if (C->CompareAddress && *mail->ReplyTo.Address) if (stricmp(mail->From.Address, mail->ReplyTo.Address))
  991.    {
  992.       char buffer[SIZE_LARGE];
  993.       sprintf(buffer, GetStr(MSG_MA_CompareReq), mail->From.Address, mail->ReplyTo.Address);
  994.       switch (MUI_Request(G->App, G->MA->GUI.WI, 0, NULL, GetStr(MSG_MA_Compare2ReqOpt), buffer))
  995.       {
  996.          case 2: pe = &mail->ReplyTo; break;
  997.          case 1: pe = &mail->From; break;
  998.          case 0: pe = NULL;
  999.       }
  1000.    }
  1001.    return pe;
  1002. }
  1003. ///
  1004. /// MA_GetAddress
  1005. //  Stores address from a list of messages to the address book
  1006. void MA_GetAddress(struct Mail **mlist)
  1007. {
  1008.    int i, j, winnum, num = (int)mlist[0], mode = AET_USER;
  1009.    struct Folder *folder = mlist[2]->Folder;
  1010.    BOOL outgoing = folder ? OUTGOING(folder->Type) : FALSE;
  1011.    struct ExtendedMail *email;
  1012.  
  1013.    if (num == 1)
  1014.    {
  1015.       if (outgoing && mlist[2]->Flags & MFLAG_MULTIRCPT) mode = AET_LIST;
  1016.    }
  1017.    else mode = AET_LIST;
  1018.    if (C->UseCManager)
  1019.    {
  1020. /*
  1021.       struct CMUser *user;
  1022.       if (mode == AET_USER) if (user = CM_AllocEntry(CME_USER))
  1023.       {
  1024.          char *p;
  1025.          stccpy(user->Address, pe->Address, 80);
  1026.          stccpy(user->Name, pe->RealName, 80);
  1027.          if (p = strchr(user->Name, ' ')) { *p = 0; stccpy(user->LastName, p, 80); }
  1028.          CM_AddEntry(user);
  1029.          CM_FreeEntry(user);
  1030.       }
  1031. */
  1032.    }
  1033.    else
  1034.    {
  1035.       struct Person *pe = NULL;
  1036.       if (mode == AET_USER)
  1037.       {
  1038.          pe = outgoing ? &(mlist[2]->To) : MA_GetAddressSelect(mlist[2]);
  1039.          if (!pe) return;
  1040.       }
  1041.       DoMethod(G->App, MUIM_CallHook, &AB_OpenHook, ABM_EDIT);
  1042.       if ((winnum = EA_Init(mode, NULL)) >= 0)
  1043.          if (mode == AET_USER)
  1044.          {
  1045.             setstring(G->EA[winnum]->GUI.ST_REALNAME, pe->RealName);
  1046.             setstring(G->EA[winnum]->GUI.ST_ADDRESS, pe->Address);
  1047.          }
  1048.          else
  1049.             for (i = 2; i < num+2; i++)
  1050.             {
  1051.                if (outgoing)
  1052.                {
  1053.                   DoMethod(G->EA[winnum]->GUI.LV_MEMBER, MUIM_List_InsertSingle, BuildAddrName2(&(mlist[i]->To)), MUIV_List_Insert_Bottom);
  1054.                   if (mlist[i]->Flags & MFLAG_MULTIRCPT) if (email = MA_ExamineMail(mlist[i]->Folder, mlist[i]->MailFile, NULL, TRUE))
  1055.                   {
  1056.                      for (j = 0; j < email->NoSTo; j++) DoMethod(G->EA[winnum]->GUI.LV_MEMBER, MUIM_List_InsertSingle, BuildAddrName2(&(email->STo[j])), MUIV_List_Insert_Bottom);
  1057.                      for (j = 0; j < email->NoCC; j++) DoMethod(G->EA[winnum]->GUI.LV_MEMBER, MUIM_List_InsertSingle, BuildAddrName2(&(email->CC[j])), MUIV_List_Insert_Bottom);
  1058.                      MA_FreeEMailStruct(email);
  1059.                   }
  1060.                }
  1061.                else
  1062.                   DoMethod(G->EA[winnum]->GUI.LV_MEMBER, MUIM_List_InsertSingle, BuildAddrName2(GetReturnAddress(mlist[i])), MUIV_List_Insert_Bottom);
  1063.             }
  1064.    }
  1065. }
  1066. ///
  1067. /// MA_GetAddressFunc
  1068. //  Stores addresses from selected messages to the address book
  1069. SAVEDS void MA_GetAddressFunc(void)
  1070. {
  1071.    struct Mail **mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS);
  1072.    if (mlist)
  1073.    {
  1074.       MA_GetAddress(mlist);
  1075.       free(mlist);
  1076.    }
  1077. }
  1078. MakeHook(MA_GetAddressHook, MA_GetAddressFunc);
  1079. ///
  1080. /// MA_PopNow
  1081. //  Fetches new mail from POP3 account(s)
  1082. void MA_PopNow(int mode, int pop)
  1083. {
  1084.    if (G->TR) return;
  1085.    if (C->UpdateStatus) MA_UpdateStatus();
  1086.    MA_StartMacro(MACRO_PREGET, itoa(mode-POP_USER));
  1087.    TR_GetMailFromNextPOP(TRUE, pop, mode);
  1088. }
  1089. SAVEDS ASM void MA_PopNowFunc(REG(a1) int *arg)
  1090. {
  1091.    ULONG qual = (ULONG)arg[2];
  1092.    if (arg[3]) return; // Toolbar qualifier bug work-around
  1093.    if (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) G->TR_Exchange = TRUE;
  1094.    MA_PopNow(arg[0],arg[1]);
  1095. }
  1096. MakeHook(MA_PopNowHook, MA_PopNowFunc);
  1097. ///
  1098.  
  1099. /*** Sub-button functions ***/
  1100. /// MA_AllocRules
  1101. //  Allocates and initializes search structures for filters
  1102. int MA_AllocRules(struct Search **search, int mode)
  1103. {
  1104.    int scnt = 0, i, j, stat;
  1105.    struct Rule *rule;
  1106.  
  1107.    for (i = 0; i < MAXRU; i++) if (rule = C->RU[i])
  1108.    {
  1109.       if (mode == APPLY_AUTO && !rule->ApplyToNew) continue;
  1110.       if (mode == APPLY_USER && !rule->ApplyOnReq) continue;
  1111.       if (mode == APPLY_SENT && !rule->ApplyToSent) continue;
  1112.       if (mode == APPLY_REMOTE && !rule->Remote) continue;
  1113.       for (j = 0; j < 2; j++)
  1114.       {
  1115.          search[scnt+j*MAXRU] = malloc(sizeof(struct Search));
  1116.          stat = 0;
  1117.          if (rule->Field[j] == 11) for (; stat < 8; stat++) if (!stricmp(rule->Match[j], Status[stat])) break;
  1118.          FI_PrepareSearch(search[scnt+j*MAXRU], rule->Field[j], rule->CaseSens[j], rule->SubField[j], rule->Comparison[j], stat, rule->Substring[j], rule->Match[j], rule->CustomField[j]);
  1119.          search[scnt+j*MAXRU]->Rule = rule;
  1120.       }
  1121.       scnt++;
  1122.    }
  1123.    return scnt;
  1124. }
  1125. ///
  1126. /// MA_FreeRules
  1127. //  Frees filter search structures
  1128. void MA_FreeRules(struct Search **search, int scnt)
  1129. {
  1130.    int i, j;
  1131.    for (i = 0; i < scnt; i++) for (j = 0; j < 2; j++)
  1132.    {
  1133.       FreeData2D(&(search[i+j*MAXRU]->List));
  1134.       free(search[i+j*MAXRU]);
  1135.    }
  1136. }
  1137. ///
  1138. /// MA_ExecuteRuleAction
  1139. //  Applies filter action to a message
  1140. BOOL MA_ExecuteRuleAction(struct Rule *rule, struct Mail *mail)
  1141. {
  1142.    struct Mail *mlist[3];
  1143.    struct Folder* fo;
  1144.    mlist[0] = (struct Mail *)1; mlist[1] = NULL; mlist[2] = mail;
  1145.    if ((rule->Actions & 1) == 1) if (*rule->BounceTo)
  1146.    {
  1147.       G->RRs.Bounced++;
  1148.       MA_NewBounce(mail, TRUE);
  1149.       setstring(G->WR[2]->GUI.ST_TO, rule->BounceTo);
  1150.       DoMethod(G->App, MUIM_CallHook, &WR_NewMailHook, WRITE_QUEUE, 2);
  1151.    }
  1152.    if ((rule->Actions & 2) == 2) if (*rule->ForwardTo)
  1153.    {
  1154.       G->RRs.Forwarded++;
  1155.       MA_NewForward(mlist, TRUE);
  1156.       setstring(G->WR[2]->GUI.ST_TO, rule->ForwardTo);
  1157.       WR_NewMail(WRITE_QUEUE, 2);
  1158.    }
  1159.    if ((rule->Actions & 4) == 4) if (*rule->ReplyFile)
  1160.    {
  1161.       MA_NewReply(mlist, TRUE);
  1162.       FileToEditor(rule->ReplyFile, G->WR[2]->GUI.TE_EDIT);
  1163.       WR_NewMail(WRITE_QUEUE, 2);
  1164.       G->RRs.Replied++;
  1165.    }
  1166.    if ((rule->Actions & 8) == 8) if (*rule->ExecuteCmd)
  1167.    {
  1168.       char buf[SIZE_COMMAND+SIZE_PATHFILE];
  1169.       strcpy(buf, rule->ExecuteCmd); strcat(buf, " ");
  1170.       strcat(buf, GetMailFile(NULL, NULL, mail));
  1171.       ExecuteCommand(buf, FALSE, NULL);
  1172.       G->RRs.Executed++;
  1173.    }
  1174.    if ((rule->Actions & 16) == 16) if (*rule->PlaySound)
  1175.    {
  1176.       PlaySound(rule->PlaySound);
  1177.    }
  1178.    if ((rule->Actions & 32) == 32) if (fo = FO_GetFolderByName(rule->MoveTo, NULL)) if (mail->Folder != fo)  // Move
  1179.    {
  1180.       G->RRs.Moved++;
  1181.       if (fo->LoadedMode != 2 && (fo->XPKType&1)) fo->Flags |= FOFL_FREEXS;
  1182.       MA_MoveCopy(mail, mail->Folder, fo, FALSE);
  1183.       return FALSE;
  1184.    }
  1185.    if ((rule->Actions & 64) == 64)
  1186.    {
  1187.       G->RRs.Deleted++;
  1188.       if (mail->Flags & MFLAG_SENDMDN) if (mail->Status == STATUS_NEW || mail->Status == STATUS_UNR) RE_DoMDN(MDN_DELE|MDN_AUTOACT, mail);
  1189.       MA_DeleteSingle(mail, FALSE);
  1190.       return FALSE;
  1191.    }
  1192.    return TRUE;
  1193. }
  1194. ///
  1195. /// MA_ApplyRulesFunc
  1196. //  Apply filters
  1197. SAVEDS ASM void MA_ApplyRulesFunc(REG(a1) int *arg)
  1198. {
  1199.    struct Mail *mail, **mlist = NULL;
  1200.    struct Folder *folder;
  1201.    int m, i, mode = arg[0], scnt, matches = 0, minselected = (arg[1] & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) ? 1 : 2;
  1202.    struct Search *search[2*MAXRU];
  1203.    APTR lv = G->MA->GUI.NL_MAILS;
  1204.    char buf[SIZE_LARGE];
  1205.  
  1206.    if (arg[2]) return; // Toolbar qualifier bug work-around
  1207.    folder = (mode == APPLY_AUTO) ? FO_GetFolderByType(FT_INCOMING, NULL) : FO_GetCurrentFolder();
  1208.    if (mode == APPLY_USER && folder->Type != FT_INCOMING)
  1209.    {
  1210.       sprintf(buf, GetStr(MSG_MA_ConfirmFilter), folder->Name);
  1211.       if (!MUI_Request(G->App, G->MA->GUI.WI, 0, GetStr(MSG_MA_ConfirmReq), GetStr(MSG_YesNoReq), buf)) return;
  1212.    }
  1213.    clear(&G->RRs, sizeof(struct RuleResult));
  1214.    set(lv, MUIA_NList_Quiet, TRUE); G->AppIconQuiet = TRUE;
  1215.    if (scnt = MA_AllocRules(search, mode))
  1216.    {
  1217.       if (mode == APPLY_USER || mode == APPLY_RX || mode == APPLY_RX_ALL) if (mlist = MA_CreateMarkedList(lv)) if ((int)mlist[0] < minselected) { free(mlist); mlist = NULL; }
  1218.       if (!mlist) mlist = MA_CreateFullList(folder);
  1219.       if (mlist)
  1220.       {
  1221.          Busy(GetStr(MSG_BusyFiltering), "", 0, (int)*mlist);
  1222.          for (m = 0; m < (int)*mlist; m++)
  1223.          {
  1224.             mail = mlist[m+2];
  1225.             if ((mode == APPLY_AUTO || mode == APPLY_RX) && mail->Status != STATUS_NEW) continue;
  1226.             G->RRs.Checked++;
  1227.             for (i = 0; i < scnt; i++)
  1228.             {
  1229.                DoMethod(G->App, MUIM_Application_InputBuffered);
  1230.                if (FI_DoComplexSearch(search[i], search[i]->Rule->Combine, search[i+MAXRU], mail))
  1231.                {
  1232.                   matches++;
  1233.                   if (!MA_ExecuteRuleAction(search[i]->Rule, mail)) break;
  1234.                }
  1235.             }
  1236.             Busy(NULL, NULL, m, 0);
  1237.          }
  1238.          free(mlist);
  1239.          if (G->RRs.Moved) MA_FlushIndexes(FALSE);
  1240.          if (G->RRs.Checked) AppendLog(26, GetStr(MSG_LOG_Filtering), (void *)(G->RRs.Checked), folder->Name, (void *)matches, "");
  1241.          Busy("", NULL,  0, 0);
  1242.       }
  1243.       MA_FreeRules(search, scnt);
  1244.    }
  1245.    set(lv, MUIA_NList_Quiet, FALSE); G->AppIconQuiet = FALSE;
  1246.    DisplayStatistics(NULL);
  1247.    if (G->RRs.Checked && mode == APPLY_USER)
  1248.    {
  1249.       sprintf(buf, GetStr(MSG_MA_FilterStats), G->RRs.Checked, G->RRs.Forwarded, G->RRs.Moved, G->RRs.Deleted);
  1250.       MUI_Request(G->App, G->MA->GUI.WI, 0, NULL, GetStr(MSG_OkayReq), buf);
  1251.    }
  1252. }
  1253. MakeHook(MA_ApplyRulesHook, MA_ApplyRulesFunc);
  1254. ///
  1255. /// MA_SendMList
  1256. //  Sends a list of messages
  1257. BOOL MA_SendMList(struct Mail **mlist)
  1258. {
  1259.    BOOL success = FALSE;
  1260.    MA_StartMacro(MACRO_PRESEND, NULL);
  1261.    if (TR_OpenTCPIP())
  1262.    {
  1263.       if (CO_IsValid()) if (G->TR = TR_New(TR_SEND))
  1264.       {
  1265.          if (SafeOpenWindow(G->TR->GUI.WI)) success = TR_ProcessSEND(mlist);
  1266.          else { MA_ChangeTransfer(TRUE); DisposeModulePush(&G->TR); }
  1267.       }
  1268.       TR_CloseTCPIP();
  1269.    }
  1270.    else ER_NewError(GetStr(MSG_ER_NoTCP), NULL, NULL);
  1271.    MA_StartMacro(MACRO_POSTSEND, NULL);
  1272.    return success;
  1273. }
  1274. ///
  1275. /// MA_Send
  1276. //  Sends selected or all messages
  1277. BOOL MA_Send(int sendpos)
  1278. {
  1279.    struct Mail **mlist;
  1280.    APTR lv = G->MA->GUI.NL_MAILS;
  1281.    BOOL success = FALSE;
  1282.    if (!G->TR)
  1283.    {
  1284.       MA_ChangeFolder(FO_GetFolderByType(FT_OUTGOING, NULL));
  1285.       if (sendpos == SEND_ALL) DoMethod(lv, MUIM_NList_Select, MUIV_NList_Select_All, MUIV_NList_Select_On, NULL);
  1286.       if (mlist = MA_CreateMarkedList(lv))
  1287.       {
  1288.          success = MA_SendMList(mlist);
  1289.          free(mlist);
  1290.       }
  1291.    }
  1292.    return success;
  1293. }
  1294. SAVEDS ASM void MA_SendFunc(REG(a1) int *arg)
  1295. {
  1296.    MA_Send(arg[0]);
  1297. }
  1298. MakeHook(MA_SendHook, MA_SendFunc);
  1299. ///
  1300.  
  1301. /*** Menu options ***/
  1302. /// MA_SetStatusTo
  1303. //  Sets status of selectes messages
  1304. void MA_SetStatusTo(int status)
  1305. {
  1306.    APTR lv = G->MA->GUI.NL_MAILS;
  1307.    struct Mail **mlist;
  1308.  
  1309.    if (mlist = MA_CreateMarkedList(lv))
  1310.    {
  1311.       int i;
  1312.       set(lv, MUIA_NList_Quiet, TRUE);
  1313.       for (i = 0; i < (int)*mlist; i++) if (mlist[i+2]->Status != status) MA_SetMailStatus(mlist[i+2], status);
  1314.       set(lv, MUIA_NList_Quiet, FALSE);
  1315.       free(mlist);
  1316.       DisplayStatistics(NULL);
  1317.    }
  1318. }
  1319. SAVEDS ASM void MA_SetStatusToFunc(REG(a1) int *arg)
  1320. {
  1321.    MA_SetStatusTo(*arg);
  1322. }
  1323. MakeHook(MA_SetStatusToHook, MA_SetStatusToFunc);
  1324. ///
  1325. /// MA_SelectAllFunc
  1326. //  Selects all messages
  1327. SAVEDS void MA_SelectAllFunc(void)
  1328. {
  1329.    DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_Select, MUIV_NList_Select_All, MUIV_NList_Select_On, NULL);
  1330. }
  1331. MakeHook(MA_SelectAllHook, MA_SelectAllFunc);
  1332. ///
  1333. /// MA_DeleteOldFunc
  1334. //  Deletes old messages
  1335. SAVEDS void MA_DeleteOldFunc(void)
  1336. {
  1337.    struct Folder **flist;
  1338.    struct DateStamp today;
  1339.    long today_days;
  1340.    int f;
  1341.    struct Mail *mail, *next;
  1342.  
  1343.    Busy(GetStr(MSG_BusyDeletingOld), "", 0, 0);
  1344.    DateStamp(&today); today_days = today.ds_Days;
  1345.    if (flist = FO_CreateList())
  1346.    {
  1347.       for (f = 1; f <= (int)*flist; f++) if (flist[f]->MaxAge) if (MA_GetIndex(flist[f]))
  1348.          for (mail = flist[f]->Messages; mail; mail = next)
  1349.          {
  1350.             next = mail->Next;
  1351.             today.ds_Days = today_days - flist[f]->MaxAge;
  1352.             if (CompareDates(&today, &(mail->Date)) < 0)
  1353.                if (flist[f]->Type == FT_DELETED || (mail->Status != STATUS_NEW && mail->Status != STATUS_UNR))
  1354.                   MA_DeleteSingle(mail, C->RemoveOnQuit);
  1355.          }
  1356.       free(flist);
  1357.    }
  1358.    BusyEnd;
  1359. }
  1360. MakeHook(MA_DeleteOldHook, MA_DeleteOldFunc);
  1361. ///
  1362. /// MA_DeleteDeletedFunc
  1363. //  Removes messages from 'deleted' folder
  1364. SAVEDS void MA_DeleteDeletedFunc(void)
  1365. {       
  1366.    int i = 0;
  1367.    struct Mail *mail;
  1368.    struct Folder *folder = FO_GetFolderByType(FT_DELETED, NULL);
  1369.  
  1370.    Busy(GetStr(MSG_BusyEmptyingTrash), "", 0, folder->Total);
  1371.    for (mail = folder->Messages; mail; mail = mail->Next)
  1372.    {
  1373.       Busy(NULL, NULL, i++, 0);
  1374.       AppendLogVerbose(21, GetStr(MSG_LOG_DeletingVerbose), AddrName(mail->From), mail->Subject, folder->Name, "");
  1375.       DeleteFile(GetMailFile(NULL, NULL, mail));
  1376.    }
  1377.    ClearMailList(folder, TRUE);
  1378.    MA_ExpireIndex(folder);
  1379.    if (FO_GetCurrentFolder() == folder) DisplayMailList(folder, G->MA->GUI.NL_MAILS);
  1380.    if (i) AppendLogNormal(20, GetStr(MSG_LOG_Deleting), (void *)i, folder->Name, "", "");
  1381.    DisplayStatistics(folder);
  1382.    BusyEnd;
  1383. }            
  1384. MakeHook(MA_DeleteDeletedHook, MA_DeleteDeletedFunc);
  1385. ///
  1386. /// MA_RescanIndexFunc
  1387. //  Updates index of current folder
  1388. SAVEDS void MA_RescanIndexFunc(void)
  1389. {
  1390.    struct Folder *folder = FO_GetCurrentFolder();
  1391.  
  1392.    MA_ScanMailBox(folder);
  1393.    MA_SaveIndex(folder);
  1394.    MA_ChangeFolder(NULL);
  1395. }
  1396. MakeHook(MA_RescanIndexHook, MA_RescanIndexFunc);
  1397. ///
  1398. /// MA_ExportMessages
  1399. //  Saves messages to a UUCP mailbox file
  1400. BOOL MA_ExportMessages(BOOL all, char *filename, BOOL append)
  1401. {
  1402.    BOOL success = FALSE;
  1403.    char outname[SIZE_PATHFILE];
  1404.    struct Mail **mlist;
  1405.    if (all) mlist = MA_CreateFullList(FO_GetCurrentFolder());
  1406.    else mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS);
  1407.    if (mlist)
  1408.    {
  1409.       if (!filename) if (ReqFile(ASL_IMPORT, G->MA->GUI.WI, GetStr(MSG_MA_ExportMessages), 1, C->DetachDir, ""))
  1410.       {
  1411.          strmfp(filename = outname, G->ASLReq[ASL_IMPORT]->fr_Drawer, G->ASLReq[ASL_IMPORT]->fr_File);
  1412.          if (FileExists(filename))
  1413.          {
  1414.             switch (MUI_Request(G->App, G->MA->GUI.WI, 0, GetStr(MSG_MA_ExportMessages), GetStr(MSG_MA_ExportAppendOpts), GetStr(MSG_MA_ExportAppendReq)))
  1415.             {
  1416.                case 1: append = FALSE; break;
  1417.                case 2: append = TRUE; break;
  1418.                case 0: filename = NULL;
  1419.             }
  1420.          }
  1421.       }
  1422.       if (filename) if (G->TR = TR_New(TR_EXPORT))
  1423.       {
  1424.          if (SafeOpenWindow(G->TR->GUI.WI)) success = TR_ProcessEXPORT(filename, mlist, append);
  1425.          else {  MA_ChangeTransfer(TRUE); DisposeModulePush(&G->TR); }
  1426.       }
  1427.       free(mlist);
  1428.    }
  1429.    return success;
  1430. }
  1431. SAVEDS ASM void MA_ExportMessagesFunc(REG(a1) int *arg)
  1432. {
  1433.    MA_ExportMessages((BOOL)*arg, NULL, FALSE);
  1434. }
  1435. MakeHook(MA_ExportMessagesHook, MA_ExportMessagesFunc);
  1436. ///
  1437. /// MA_ImportMessages
  1438. //  Imports messages from a UUCP mailbox file
  1439. BOOL MA_ImportMessages(char *fname)
  1440. {
  1441.    FILE *fh;
  1442.  
  1443.    if (fh = fopen(fname, "r"))
  1444.    {
  1445.       if (G->TR = TR_New(TR_IMPORT))
  1446.       {
  1447.          stccpy(G->TR->ImportFile, fname, SIZE_PATHFILE);
  1448.          TR_SetWinTitle(TRUE, FilePart(fname));
  1449.          G->TR->ImportBox = FO_GetCurrentFolder();
  1450.          if (SafeOpenWindow(G->TR->GUI.WI))
  1451.          {
  1452.             TR_GetMessageList_IMPORT(fh);
  1453.             fclose(fh);
  1454.             return TRUE;
  1455.          }
  1456.          else { MA_ChangeTransfer(TRUE); DisposeModulePush(&G->TR); }
  1457.       }
  1458.       fclose(fh);
  1459.    }
  1460.    return FALSE;
  1461. }
  1462. SAVEDS void MA_ImportMessagesFunc(void)
  1463. {
  1464.    if (ReqFile(ASL_IMPORT, G->MA->GUI.WI, GetStr(MSG_MA_ImportMessages), 0, C->DetachDir, ""))
  1465.    {
  1466.       char inname[SIZE_PATHFILE];
  1467.       strmfp(inname, G->ASLReq[ASL_IMPORT]->fr_Drawer, G->ASLReq[ASL_IMPORT]->fr_File);
  1468.       MA_ImportMessages(inname);
  1469.    }
  1470. }
  1471. MakeHook(MA_ImportMessagesHook, MA_ImportMessagesFunc);
  1472. ///
  1473. /// MA_MoveMessageFunc
  1474. //  Moves selected messages to a user specified folder
  1475. SAVEDS void MA_MoveMessageFunc(void)
  1476. {
  1477.    struct Folder *src = FO_GetCurrentFolder(), *dst;
  1478.    if (dst = FolderRequest(GetStr(MSG_MA_MoveMsg), GetStr(MSG_MA_MoveMsgReq), GetStr(MSG_MA_MoveGad), GetStr(MSG_Cancel), src, G->MA->GUI.WI))
  1479.       MA_MoveCopy(NULL, src, dst, FALSE);
  1480. }
  1481. MakeHook(MA_MoveMessageHook, MA_MoveMessageFunc);
  1482. ///
  1483. /// MA_CopyMessageFunc
  1484. //  Copies selected messages to a user specified folder
  1485. SAVEDS void MA_CopyMessageFunc(void)
  1486. {
  1487.    struct Folder *src = FO_GetCurrentFolder(), *dst;
  1488.    if (dst = FolderRequest(GetStr(MSG_MA_CopyMsg), GetStr(MSG_MA_MoveMsgReq), GetStr(MSG_MA_CopyGad), GetStr(MSG_Cancel), NULL, G->MA->GUI.WI))
  1489.       MA_MoveCopy(NULL, src, dst, TRUE);
  1490. }
  1491. MakeHook(MA_CopyMessageHook, MA_CopyMessageFunc);
  1492. ///
  1493. /// MA_ChangeSubject
  1494. //  Changes subject of a message
  1495. void MA_ChangeSubject(struct Mail *mail, char *subj)
  1496. {
  1497.    struct Folder *fo = mail->Folder;
  1498.    int f;
  1499.    FILE *oldfh, *newfh;
  1500.    char *oldfile, newfile[SIZE_PATHFILE], fullfile[SIZE_PATHFILE], buf[SIZE_LINE];
  1501.  
  1502.    if (!strcmp(subj, mail->Subject)) return;
  1503.    if (!StartUnpack(oldfile = GetMailFile(NULL, NULL, mail), fullfile, fo)) return;
  1504.    strmfp(newfile, GetFolderDir(fo), "00000.tmp");
  1505.    if (newfh = fopen(newfile, "w"))
  1506.    {
  1507.       if (oldfh = fopen(fullfile, "r"))
  1508.       {
  1509.          BOOL infield = FALSE, inbody = FALSE, hasorigsubj = FALSE;
  1510.          while (fgets(buf, SIZE_LINE, oldfh))
  1511.          {
  1512.             if (*buf == '\n' && !inbody)
  1513.             {
  1514.                inbody = TRUE;
  1515.                if (!hasorigsubj) EmitHeader(newfh, "X-Original-Subject", mail->Subject);
  1516.                EmitHeader(newfh, "Subject", subj);
  1517.             }
  1518.             if (!ISpace(*buf))
  1519.             {
  1520.                infield = !strnicmp(buf, "subject:", 8);
  1521.                if (!strnicmp(buf, "x-original-subject:", 19)) hasorigsubj = TRUE;
  1522.             }
  1523.             if (!infield || inbody) fputs(buf, newfh);
  1524.          }
  1525.          fclose(oldfh);
  1526.          DeleteFile(oldfile);
  1527.       }
  1528.       fclose(newfh);
  1529.       f = FileSize(newfile); fo->Size += f - mail->Size; mail->Size = f;
  1530.       AppendLog(82, GetStr(MSG_LOG_ChangingSubject), mail->Subject, mail->MailFile, fo->Name, subj);
  1531.       strcpy(mail->Subject, subj);
  1532.       MA_ExpireIndex(fo);
  1533.       if (fo->XPKType > 1) DoPack(newfile, oldfile, fo);
  1534.       else RenameFile(newfile, oldfile);
  1535.       MA_SetMailStatus(mail, mail->Status);
  1536.    }
  1537.    FinishUnpack(fullfile);
  1538. }
  1539. ///
  1540. /// MA_ChangeSubjectFunc
  1541. //  Changes subject of selected messages
  1542. SAVEDS void MA_ChangeSubjectFunc(void)
  1543. {
  1544.    struct Mail **mlist, *mail;
  1545.    int i, selected;
  1546.    BOOL ask = TRUE;
  1547.    APTR lv = G->MA->GUI.NL_MAILS;
  1548.    char subj[SIZE_SUBJECT];
  1549.  
  1550.    if (!(mlist = MA_CreateMarkedList(lv))) return;
  1551.    selected = (int)*mlist;
  1552.    for (i = 0; i < selected; i++)
  1553.    {
  1554.       mail = mlist[i+2];
  1555.       if (ask)
  1556.       {
  1557.          strcpy(subj, mail->Subject);
  1558.          switch (StringRequest(subj, SIZE_SUBJECT, GetStr(MSG_MA_ChangeSubj), GetStr(MSG_MA_ChangeSubjReq), GetStr(MSG_Okay), (i || selected == 1) ? NULL : GetStr(MSG_MA_All), GetStr(MSG_Cancel), FALSE, G->MA->GUI.WI))
  1559.          {
  1560.             case 0: free(mlist); return;
  1561.             case 2: ask = FALSE;
  1562.          }
  1563.       }
  1564.       MA_ChangeSubject(mail, subj);
  1565.    }
  1566.    free(mlist);
  1567.    DoMethod(lv, MUIM_NList_Redraw, MUIV_NList_Redraw_All);
  1568.    DisplayStatistics(0);
  1569. }
  1570. MakeHook(MA_ChangeSubjectHook, MA_ChangeSubjectFunc);
  1571. ///
  1572. /// MA_AboutMUIFunc
  1573. //  Displays 'About MUI' window
  1574. SAVEDS void MA_AboutMUIFunc(void)
  1575. {
  1576.    static APTR muiwin = NULL;
  1577.  
  1578.    if (!muiwin) muiwin = AboutmuiObject,
  1579.       MUIA_Window_RefWindow, G->MA->GUI.WI,
  1580.       MUIA_Aboutmui_Application, G->App,
  1581.    End;
  1582.    if (muiwin) SafeOpenWindow(muiwin); else DisplayBeep(0);
  1583. }
  1584. MakeHook(MA_AboutMUIHook, MA_AboutMUIFunc);
  1585. ///
  1586. /// MA_CheckVersionFunc
  1587. //  Checks YAM homepage for new program versions
  1588. SAVEDS void MA_CheckVersionFunc(void)
  1589. {
  1590.    struct TempFile *tf;
  1591.    int mon, day, year;
  1592.    long thisver, currver;
  1593.    char newver[SIZE_SMALL], buf[SIZE_LARGE];
  1594.  
  1595.    if (TR_OpenTCPIP())
  1596.    {
  1597.       sscanf(YAMDATE, "%ld.%ld.%ld", &day, &mon, &year);
  1598.       thisver = (year<78 ? 1000000:0)+year*10000+mon*100+day;
  1599.       Busy(GetStr(MSG_BusyGettingVerInfo), "", 0, 0);
  1600.       tf = OpenTempFile(NULL);
  1601.       if (TR_DownloadURL(C->SupportSite, "files/", "version", tf->Filename))
  1602.       {
  1603.          if (tf->FP = fopen(tf->Filename,"r"))
  1604.          {
  1605.             fscanf(tf->FP, "%ld.%ld.%ld", &day, &mon, &year);
  1606.             GetLine(tf->FP, newver, SIZE_SMALL);
  1607.             currver = (year<78 ? 1000000:0)+year*10000+mon*100+day;
  1608.             sprintf(buf, GetStr(MSG_MA_LatestVersion), &newver[1], day, mon, year, __VERSION__, __VERDATE__,
  1609.                currver > thisver ? GetStr(MSG_MA_NewVersion) : GetStr(MSG_MA_NoNewVersion));
  1610.             if (MUI_Request(G->App, G->MA->GUI.WI, 0, GetStr(MSG_MA_CheckVersion), GetStr(MSG_MA_VersionReqOpt), buf)) GotoURL(C->SupportSite);
  1611.          }
  1612.          else ER_NewError(GetStr(MSG_ER_CantOpenTempfile), tf->Filename, NULL);
  1613.       }
  1614.       CloseTempFile(tf);
  1615.       BusyEnd;
  1616.       TR_CloseTCPIP();
  1617.    }
  1618.    else ER_NewError(GetStr(MSG_ER_NoTCP), NULL, NULL);
  1619. }
  1620. MakeHook(MA_CheckVersionHook, MA_CheckVersionFunc);
  1621. ///
  1622. /// MA_ShowErrorsFunc
  1623. //  Opens error message window
  1624. SAVEDS void MA_ShowErrorsFunc(void)
  1625. {
  1626.    ER_NewError(NULL, NULL, NULL);
  1627. }
  1628. MakeHook(MA_ShowErrorsHook, MA_ShowErrorsFunc);
  1629. ///
  1630. /// MA_StartMacro
  1631. //  Launches user-defined ARexx script or AmigaDOS command
  1632. BOOL MA_StartMacro(int num, char *param)
  1633. {
  1634.    BPTR fh;
  1635.    char command[SIZE_LARGE], *wtitle = "CON:////YAM ARexx Window/AUTO";
  1636.    struct RexxMsg *sentrm;
  1637.  
  1638.    strcpy(command, C->RX[num].Script);
  1639.    if (!*command) return 0;
  1640.    if (param) { strcat(command, " "); strcat(command, param); }
  1641.    if (C->RX[num].IsAmigaDOS)
  1642.    {
  1643.       Busy(" ", "", 0, 0);
  1644.       ExecuteCommand(command, !C->RX[num].WaitTerm, C->RX[num].UseConsole ? NULL : OUT_NIL);
  1645.       BusyEnd;
  1646.    }
  1647.    else
  1648.    {
  1649.       if (!(fh = Open(C->RX[num].UseConsole ? wtitle : "NIL:", MODE_NEWFILE)))
  1650.       {
  1651.          ER_NewError(GetStr(MSG_ER_ErrorConsole), NULL, NULL);
  1652.          return FALSE;
  1653.       }
  1654.       if (!(sentrm = SendRexxCommand(G->RexxHost, command, fh)))
  1655.       {
  1656.          Close(fh);
  1657.          ER_NewError(GetStr(MSG_ER_ErrorARexxScript), command, NULL);
  1658.          return FALSE;
  1659.       }
  1660.       if (C->RX[num].WaitTerm)
  1661.       {
  1662.          extern void DoRXCommand( struct RexxHost *, struct RexxMsg *);
  1663.          struct RexxMsg *rm;
  1664.          BOOL waiting = TRUE;
  1665.          Busy(" ", "", 0, 0);
  1666.          do
  1667.          {
  1668.             WaitPort(G->RexxHost->port);
  1669.             while (rm = (struct RexxMsg *)GetMsg(G->RexxHost->port))
  1670.             {
  1671.                if ((rm->rm_Action & RXCODEMASK) != RXCOMM) ReplyMsg((struct Message *)rm);
  1672.                else if (rm->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
  1673.                {
  1674.                   struct RexxMsg *org = (struct RexxMsg *)rm->rm_Args[15];
  1675.                   if (org)
  1676.                   {
  1677.                      if (rm->rm_Result1) ReplyRexxCommand(org, 20, ERROR_NOT_IMPLEMENTED, NULL);
  1678.                      else ReplyRexxCommand(org, 0, 0, (char *)rm->rm_Result2);
  1679.                   }
  1680.                   if (rm == sentrm) waiting = FALSE;
  1681.                   FreeRexxCommand(rm);
  1682.                   --G->RexxHost->replies;
  1683.                }
  1684.                else if (rm->rm_Args[0]) DoRXCommand(G->RexxHost, rm);
  1685.                else ReplyMsg((struct Message *)rm);
  1686.             }
  1687.          }
  1688.          while (waiting);
  1689.          BusyEnd;
  1690.       }
  1691.    }
  1692.    return TRUE;
  1693. }
  1694. ///
  1695. /// MA_CallRexxFunc
  1696. //  Launches a script from the ARexx menu
  1697. SAVEDS ASM void MA_CallRexxFunc(REG(a1) int *arg)
  1698. {
  1699.    char scname[SIZE_COMMAND];
  1700.    int script = *arg;
  1701.    if (script >= 0)
  1702.    {                 
  1703.       MA_StartMacro(MACRO_MEN0+script, NULL);
  1704.    }
  1705.    else
  1706.    {
  1707.       strmfp(scname, G->ProgDir, "rexx");
  1708.       if (ReqFile(ASL_REXX, G->MA->GUI.WI, GetStr(MSG_MA_ExecuteScript), 0, scname, ""))
  1709.       {
  1710.          strmfp(scname, G->ASLReq[ASL_REXX]->fr_Drawer, G->ASLReq[ASL_REXX]->fr_File);
  1711.          SendRexxCommand(G->RexxHost, scname, NULL);
  1712.       }
  1713.    }
  1714. }
  1715. MakeHook(MA_CallRexxHook, MA_CallRexxFunc);
  1716. ///
  1717.  
  1718. /*** Hooks ***/
  1719. /// PO_Window
  1720. //  Window hook for popup objects
  1721. SAVEDS ASM void PO_Window(REG(a2) Object *pop, REG(a1) Object *win)
  1722. {
  1723.    set(win, MUIA_Window_DefaultObject, pop);
  1724. }
  1725. MakeHook(PO_WindowHook, PO_Window);
  1726. ///
  1727. /// MA_LV_FConFunc
  1728. //  Folder listview construction hook
  1729. SAVEDS ASM struct Folder *MA_LV_FConFunc(REG(a1) struct Folder *fo)
  1730. {
  1731.    struct Folder *entry = malloc(sizeof(struct Folder));
  1732.    memcpy(entry, fo, sizeof(struct Folder));
  1733.    return entry;
  1734. }
  1735. MakeHook(MA_LV_FConHook, MA_LV_FConFunc);
  1736. ///
  1737. /// MA_LV_DspFunc
  1738. //  Message listview display hook
  1739. SAVEDS ASM long MA_LV_DspFunc(REG(a0) struct Hook *hook, REG(a2) char **array, REG(a1) struct Mail *entry)
  1740. {
  1741.    BOOL outbox;
  1742.    struct Folder *folder = NULL;
  1743.    int type = 0;
  1744.  
  1745.   if (G->MA) if (folder = FO_GetCurrentFolder()) type = folder->Type;
  1746.    outbox = OUTGOING(type);
  1747.    if (entry)
  1748.    {
  1749.       if (folder)
  1750.       {
  1751.          static char dispfro[SIZE_DEFAULT], dispsta[SIZE_DEFAULT], dispsiz[SIZE_SMALL];
  1752.          struct Person *pe;
  1753.          sprintf(array[0] = dispsta, "\033o[%ld]", entry->Status);
  1754.          if (entry->Importance == 1) strcat(dispsta, "\033o[12]");
  1755.          if (entry->Flags & MFLAG_CRYPT) strcat(dispsta, "\033o[15]");
  1756.          else if (entry->Flags & MFLAG_SIGNED) strcat(dispsta, "\033o[16]");
  1757.          else if (entry->Flags & MFLAG_REPORT) strcat(dispsta, "\033o[14]");
  1758.          else if (entry->Flags & MFLAG_MULTIPART) strcat(dispsta, "\033o[13]");
  1759.          array[1] = dispfro; *dispfro = 0;
  1760.          if (entry->Flags & MFLAG_MULTIRCPT) strcat(dispfro, "\033o[11]");
  1761.          pe = outbox ? &entry->To : &entry->From;
  1762.          if (type == FT_CUSTOMMIXED || type == FT_DELETED) if (!stricmp(pe->Address, C->EmailAddress))
  1763.          {
  1764.             pe = &entry->To; strcat(dispfro, GetStr(MSG_MA_ToPrefix));
  1765.          }
  1766.          strncat(dispfro, AddrName((*pe)), SIZE_DEFAULT-strlen(dispfro)-1);
  1767.          array[2] = AddrName((entry->ReplyTo));
  1768.          array[3] = entry->Subject;
  1769.          array[4] = DateStamp2String(&entry->Date, C->SwatchBeat ? DSS_DATEBEAT : DSS_DATETIME);
  1770.          array[5] = dispsiz; *dispsiz = 0;
  1771.          FormatSize(entry->Size, dispsiz);
  1772.          array[6] = entry->MailFile;
  1773.          array[7] = entry->Folder->Name;
  1774.       }
  1775.    }
  1776.    else
  1777.    {
  1778.       array[0] = GetStr(MSG_MA_TitleStatus);
  1779.       array[1] = GetStr(outbox ? MSG_To : MSG_From);
  1780.       array[2] = GetStr(MSG_ReturnAddress);
  1781.       array[3] = GetStr(MSG_Subject);
  1782.       array[4] = GetStr(MSG_Date);
  1783.       array[5] = GetStr(MSG_Size);
  1784.       array[6] = GetStr(MSG_Filename);
  1785.       array[7] = GetStr(MSG_Folder);
  1786.    }
  1787.    return 0;
  1788. }
  1789. MakeHook(MA_LV_DspFuncHook,MA_LV_DspFunc);
  1790. ///
  1791. /// MA_GetRealSubject
  1792. //  Strips reply prefix / mailing list name from subject
  1793. char *MA_GetRealSubject(char *sub)
  1794. {
  1795.    char *p, *pend = &sub[strlen(sub)];
  1796.    if (strlen(sub) < 3) return sub;
  1797.    if (sub[2] == ':' && !sub[3]) return "";
  1798.    if (sub[0] == '[') if (p = strchr(sub, ']')) if (p < pend-3 && p < &sub[20]) return MA_GetRealSubject(p+2);
  1799.    if (strchr(":[({", sub[2])) if (p = strchr(sub, ':')) return MA_GetRealSubject(TrimStart(++p));
  1800.    return sub;
  1801. }
  1802. ///
  1803. /// MA_MailCompare
  1804. //  Compares two messages
  1805. int MA_MailCompare(struct Mail *entry1, struct Mail *entry2, int column)
  1806. {
  1807.    static int values[9] = { 50, 35, 30, 25, 45, 60, 40, 20, 55 };
  1808.    switch (column)
  1809.    {
  1810.       case 0: return -(values[entry1->Status]+entry1->Importance)+(values[entry2->Status]+entry2->Importance);
  1811.       case 1: if (OUTGOING(entry1->Folder->Type))
  1812.                  return stricmp(*entry1->To.RealName ? entry1->To.RealName : entry1->To.Address,
  1813.                                 *entry2->To.RealName ? entry2->To.RealName : entry2->To.Address);
  1814.               else
  1815.                  return stricmp(*entry1->From.RealName ? entry1->From.RealName : entry1->From.Address,
  1816.                                 *entry2->From.RealName ? entry2->From.RealName : entry2->From.Address);
  1817.       case 2: return stricmp(*entry1->ReplyTo.RealName ? entry1->ReplyTo.RealName : entry1->ReplyTo.Address,
  1818.                              *entry2->ReplyTo.RealName ? entry2->ReplyTo.RealName : entry2->ReplyTo.Address);
  1819.       case 3: return stricmp(MA_GetRealSubject(entry1->Subject), MA_GetRealSubject(entry2->Subject));
  1820.       case 4: return CompareDates(&entry2->Date, &entry1->Date);
  1821.       case 5: return entry1->Size-entry2->Size;
  1822.       case 6: return strcmp(entry1->MailFile, entry2->MailFile);
  1823.       case 7: return stricmp(entry1->Folder->Name, entry2->Folder->Name);
  1824.    }
  1825.    return 0;
  1826. }
  1827. ///
  1828. /// MA_LV_Cmp2Func
  1829. //  Message listview sort hook
  1830. SAVEDS ASM long MA_LV_Cmp2Func(REG(a1) struct NList_CompareMessage *ncm, REG(a2) Object *obj)
  1831. {
  1832.    struct Mail *entry1 = (struct Mail *)ncm->entry1;
  1833.    struct Mail *entry2 = (struct Mail *)ncm->entry2;
  1834.    long col1 = ncm->sort_type & MUIV_NList_TitleMark_ColMask;
  1835.    long col2 = ncm->sort_type2 & MUIV_NList_TitleMark2_ColMask;
  1836.    int cmp;
  1837.  
  1838.    if (ncm->sort_type == MUIV_NList_SortType_None) return 0;
  1839.    if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask) cmp = MA_MailCompare(entry2, entry1, col1);
  1840.    else                                                cmp = MA_MailCompare(entry1, entry2, col1);
  1841.    if (cmp || col1 == col2) return cmp;
  1842.    if (ncm->sort_type2 & MUIV_NList_TitleMark2_TypeMask) cmp = MA_MailCompare(entry2, entry1, col2);
  1843.    else                                                  cmp = MA_MailCompare(entry1, entry2, col2);
  1844.    return cmp;
  1845. }
  1846. MakeHook(MA_LV_Cmp2Hook, MA_LV_Cmp2Func);
  1847. ///
  1848. /// MA_LV_FCmp2Func
  1849. //  Folder listview sort hook
  1850. SAVEDS ASM long MA_LV_FCmp2Func(REG(a1) struct NList_CompareMessage *ncm, REG(a2) Object *obj)
  1851. {
  1852.    struct Folder *entry1 = (struct Folder *)ncm->entry1;
  1853.    struct Folder *entry2 = (struct Folder *)ncm->entry2;
  1854.    int cmp = 0;
  1855.  
  1856.    if (ncm->sort_type != MUIV_NList_SortType_None)
  1857.    {
  1858.       switch (ncm->sort_type & MUIV_NList_TitleMark_ColMask)
  1859.       {
  1860.          case 0:  cmp = stricmp(entry1->Name, entry2->Name); break;
  1861.          case 1:  cmp = entry1->Total-entry2->Total; break;
  1862.          case 2:  cmp = entry1->Unread-entry2->Unread; break;
  1863.          case 3:  cmp = entry1->New-entry2->New; break;
  1864.          case 4:  cmp = entry1->Size-entry2->Size; break;
  1865.          case 10: return entry1->SortIndex-entry2->SortIndex;
  1866.       }
  1867.       if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask) cmp = -cmp;
  1868.    }
  1869.    return cmp;
  1870. }
  1871. MakeHook(MA_LV_FCmp2Hook, MA_LV_FCmp2Func);
  1872. ///
  1873.  
  1874. /*** GUI ***/
  1875. enum { MMEN_ABOUT=1,MMEN_ABOUTMUI,MMEN_VERSION,MMEN_ERRORS,MMEN_LOGIN,MMEN_HIDE,MMEN_QUIT,
  1876.        MMEN_NEWF,MMEN_NEWS,MMEN_EDITF,MMEN_DELETEF,MMEN_OSAVE,MMEN_ORESET,MMEN_SELALL,MMEN_SELNONE,MMEN_SELTOGG,MMEN_SEARCH,MMEN_FILTER,MMEN_DELDEL,MMEN_INDEX,MMEN_FLUSH,MMEN_IMPORT,MMEN_EXPORT,MMEN_GETMAIL,MMEN_GET1MAIL,MMEN_SENDMAIL,MMEN_EXMAIL,
  1877.        MMEN_READ,MMEN_EDIT,MMEN_MOVE,MMEN_COPY,MMEN_DELETE,MMEN_PRINT,MMEN_SAVE,MMEN_DETACH,MMEN_CROP,MMEN_EXPMSG,MMEN_NEW,MMEN_REPLY,MMEN_FORWARD,MMEN_BOUNCE,MMEN_SAVEADDR,MMEN_TOUNREAD,MMEN_TOREAD,MMEN_TOHOLD,MMEN_TOQUEUED,MMEN_CHSUBJ,MMEN_SEND,
  1878.        MMEN_ABOOK,MMEN_CONFIG,MMEN_USER,MMEN_MUI,MMEN_SCRIPT };
  1879. #define MMEN_MACRO   100
  1880. #define MMEN_POPHOST 150
  1881.  
  1882. /// MA_SetupDynamicMenus
  1883. //  Updates ARexx and POP3 account menu items
  1884. void MA_SetupDynamicMenus(void)
  1885. {
  1886.    int i;
  1887.    static char *shortcuts[10] = { "0","1","2","3","4","5","6","7","8","9" };
  1888.  
  1889.    if (G->MA->GUI.MN_REXX) DoMethod(G->MA->GUI.MS_MAIN, MUIM_Family_Remove, G->MA->GUI.MN_REXX);
  1890.    G->MA->GUI.MN_REXX = MenuObject, MUIA_Menu_Title, GetStr(MSG_MA_Scripts),
  1891.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_ExecuteScript), MUIA_Menuitem_Shortcut,".", MUIA_UserData,MMEN_SCRIPT, End,
  1892.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,NM_BARLABEL, End,
  1893.          End;
  1894.    for (i = 0; i < 10; i++) if (C->RX[i].Script[0])
  1895.       DoMethod(G->MA->GUI.MN_REXX, MUIM_Family_AddTail, MenuitemObject, MUIA_Menuitem_Title,C->RX[i].Name, MUIA_Menuitem_Shortcut,shortcuts[i], MUIA_UserData,MMEN_MACRO+i, End);
  1896.    DoMethod(G->MA->GUI.MS_MAIN, MUIM_Family_AddTail, G->MA->GUI.MN_REXX);
  1897.    if (G->MA->GUI.MI_CSINGLE)  DoMethod(G->MA->GUI.MN_FOLDER, MUIM_Family_Remove, G->MA->GUI.MI_CSINGLE);
  1898.    G->MA->GUI.MI_CSINGLE = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_CheckSingle), End;
  1899.    for (i = 0; i < MAXP3; i++) if (C->P3[i])
  1900.    {
  1901.       sprintf(C->P3[i]->Account, "%s@%s", C->P3[i]->User, C->P3[i]->Server);
  1902.       DoMethod(G->MA->GUI.MI_CSINGLE, MUIM_Family_AddTail, MenuitemObject, MUIA_Menuitem_Title,C->P3[i]->Account, MUIA_UserData,MMEN_POPHOST+i, End);
  1903.    }
  1904.    DoMethod(G->MA->GUI.MN_FOLDER, MUIM_Family_AddTail, G->MA->GUI.MI_CSINGLE);
  1905. }
  1906. ///
  1907. /// MA_MakeMAFormat
  1908. //  Creates format definition for message listview
  1909. void MA_MakeMAFormat(APTR lv)
  1910. {
  1911.    int i;
  1912.    int defwidth[MACOLNUM] = { -1,-1,-1,-1,-1,-1,-1 };
  1913.    char format[SIZE_LARGE];
  1914.    BOOL first = TRUE;
  1915.    *format = 0;
  1916.    for (i = 0; i < MACOLNUM; i++) if (C->MessageCols & (1<<i))
  1917.    {
  1918.       if (first) first = FALSE; else strcat(format, " BAR,");
  1919.       sprintf(&format[strlen(format)], "COL=%ld W=%ld", i, defwidth[i]);
  1920.       if (i == 5) strcat(format, " P=\033r");
  1921.    }
  1922.    strcat(format, " BAR");
  1923.    set(lv, MUIA_NList_Format, format);
  1924. }
  1925. ///
  1926. /// MA_New
  1927. //  Creates main window
  1928. struct MA_ClassData *MA_New(void)
  1929. {
  1930.    struct MA_ClassData *data;
  1931.   
  1932.    if (data = calloc(1,sizeof(struct MA_ClassData)))
  1933.    {
  1934.       APTR tb_butt[18] = { MSG_MA_TBRead,MSG_MA_TBEdit,MSG_MA_TBMove,MSG_MA_TBDelete,MSG_MA_TBGetAddr,MSG_Space,
  1935.                            MSG_MA_TBWrite,MSG_MA_TBReply,MSG_MA_TBForward,MSG_Space,
  1936.                            MSG_MA_TBGetMail,MSG_MA_TBSendAll,MSG_Space,
  1937.                            MSG_MA_TBFilter,MSG_MA_TBFind,MSG_MA_TBAddrBook,MSG_MA_TBConfig,NULL };
  1938.       APTR tb_help[18] = { MSG_HELP_MA_BT_READ,MSG_HELP_MA_BT_EDIT,MSG_HELP_MA_BT_MOVE,MSG_HELP_MA_BT_DELETE,MSG_HELP_MA_BT_GETADDRESS,NULL,
  1939.                            MSG_HELP_MA_BT_WRITE,MSG_HELP_MA_BT_REPLY,MSG_HELP_MA_BT_FORWARD,NULL,
  1940.                            MSG_HELP_MA_BT_POPNOW,MSG_HELP_MA_BT_SENDALL,NULL,
  1941.                            MSG_HELP_MA_BT_FILTER,MSG_HELP_MA_BT_SEARCH,MSG_HELP_MA_BT_ABOOK,MSG_HELP_MA_BT_CONFIG,NULL };
  1942.       int i;
  1943.       char *key = "-repeat 0", *username = C->RealName;
  1944.       struct User *user;
  1945.       for (i = 0; i < 18; i++) SetupToolbar(&(data->GUI.TB_TOOLBAR[i]), tb_butt[i]?(tb_butt[i]==MSG_Space?"":GetStr(tb_butt[i])):NULL, tb_help[i]?GetStr(tb_help[i]):NULL, 0);
  1946.       if (user = US_GetCurrentUser()) username = user->Name;
  1947.       sprintf(data->WinTitle, GetStr(MSG_MA_WinTitle), __VERSION__, username);
  1948.       data->GUI.MS_MAIN = MenustripObject,
  1949.          MUIA_Family_Child, MenuObject, MUIA_Menu_Title, GetStr(MSG_MA_Project),
  1950.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_About), MUIA_Menuitem_Shortcut,"?", MUIA_UserData,MMEN_ABOUT, End,
  1951.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_AboutMUI), MUIA_UserData,MMEN_ABOUTMUI, End,
  1952.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_CheckVersion), MUIA_UserData,MMEN_VERSION, End,
  1953.             MUIA_Family_Child, data->GUI.MI_ERRORS = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_LastErrors), MUIA_Menuitem_Enabled,FALSE, MUIA_UserData,MMEN_ERRORS, End,
  1954.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,NM_BARLABEL, End,
  1955.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_Restart), MUIA_UserData,MMEN_LOGIN, End,
  1956.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_Hide), MUIA_Menuitem_Shortcut,"H", MUIA_UserData,MMEN_HIDE, End,
  1957.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_Quit), MUIA_Menuitem_Shortcut,"Q", MUIA_UserData,MMEN_QUIT, End,
  1958.          End,
  1959.          MUIA_Family_Child, data->GUI.MN_FOLDER = MenuObject, MUIA_Menu_Title, GetStr(MSG_Folder),
  1960.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_NewFolder), MUIA_UserData,MMEN_NEWF, End,
  1961.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_NewSeparator), MUIA_UserData,MMEN_NEWS, End,
  1962.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MEdit), MUIA_UserData,MMEN_EDITF, End,
  1963.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MDelete), MUIA_UserData,MMEN_DELETEF, End,
  1964.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_SortOrder),
  1965.                MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_OSave), MUIA_UserData,MMEN_OSAVE, End,
  1966.                MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_Reset), MUIA_UserData,MMEN_ORESET, End,
  1967.             End,
  1968.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,NM_BARLABEL, End,
  1969.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MSearch), MUIA_Menuitem_Shortcut,"F", MUIA_UserData,MMEN_SEARCH, End,
  1970.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MFilter), MUIA_Menuitem_Shortcut,"I", MUIA_UserData,MMEN_FILTER, End,
  1971.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,NM_BARLABEL, End,
  1972.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_RemoveDeleted), MUIA_Menuitem_Shortcut,"Z", MUIA_UserData,MMEN_DELDEL, End,
  1973.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_UpdateIndex), MUIA_Menuitem_Shortcut,"U", MUIA_UserData,MMEN_INDEX, End,
  1974.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_FlushIndices), MUIA_UserData,MMEN_FLUSH, End,
  1975.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,NM_BARLABEL, End,
  1976.             MUIA_Family_Child, data->GUI.MI_IMPORT = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_ImportMessages), MUIA_UserData,MMEN_IMPORT, End,
  1977.             MUIA_Family_Child, data->GUI.MI_EXPORT = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_ExportMessages), MUIA_UserData,MMEN_EXPORT, End,
  1978.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,NM_BARLABEL, End,
  1979.             MUIA_Family_Child, data->GUI.MI_SENDALL = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MSendAll), MUIA_Menuitem_Shortcut,"S", MUIA_UserData,MMEN_SENDMAIL, End,
  1980.             MUIA_Family_Child, data->GUI.MI_EXCHANGE = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_Exchange), MUIA_Menuitem_Shortcut,"X", MUIA_UserData,MMEN_EXMAIL, End,
  1981.             MUIA_Family_Child, data->GUI.MI_GETMAIL = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MGetMail), MUIA_Menuitem_Shortcut,"G", MUIA_UserData,MMEN_GETMAIL, End,
  1982.         End,
  1983.          MUIA_Family_Child, MenuObject, MUIA_Menu_Title, GetStr(MSG_Message),
  1984.             MUIA_Family_Child, data->GUI.MI_READ = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MRead), MUIA_Menuitem_Shortcut,"D", MUIA_UserData,MMEN_READ, End,
  1985.             MUIA_Family_Child, data->GUI.MI_EDIT = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MEdit), MUIA_Menuitem_Shortcut,"E", MUIA_UserData,MMEN_EDIT, End,
  1986.             MUIA_Family_Child, data->GUI.MI_MOVE = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MMove), MUIA_Menuitem_Shortcut,"M", MUIA_UserData,MMEN_MOVE, End,
  1987.             MUIA_Family_Child, data->GUI.MI_COPY = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MCopy), MUIA_Menuitem_Shortcut,"Y", MUIA_UserData,MMEN_COPY, End,
  1988.             MUIA_Family_Child, data->GUI.MI_DELETE = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MDelete), MUIA_Menuitem_Shortcut,"Del", MUIA_Menuitem_CommandString,TRUE, MUIA_UserData,MMEN_DELETE, End,
  1989.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,NM_BARLABEL, End,
  1990.             MUIA_Family_Child, data->GUI.MI_PRINT = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_Print), MUIA_Menuitem_Shortcut,"P", MUIA_UserData,MMEN_PRINT, End,
  1991.             MUIA_Family_Child, data->GUI.MI_SAVE = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_Save), MUIA_Menuitem_Shortcut,"V", MUIA_UserData,MMEN_SAVE, End,
  1992.             MUIA_Family_Child, data->GUI.MI_ATTACH = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_Attachments),
  1993.                MUIA_Family_Child, data->GUI.MI_SAVEATT = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_Save), MUIA_Menuitem_Shortcut,"T", MUIA_UserData,MMEN_DETACH, End,
  1994.                MUIA_Family_Child, data->GUI.MI_REMATT = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_Crop), MUIA_Menuitem_Shortcut,"O", MUIA_UserData,MMEN_CROP, End,
  1995.             End,
  1996.             MUIA_Family_Child, data->GUI.MI_EXPMSG = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_ExportMessages), MUIA_UserData,MMEN_EXPMSG, End,
  1997.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,NM_BARLABEL, End,
  1998.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_New), MUIA_Menuitem_Shortcut,"N", MUIA_UserData,MMEN_NEW, End,
  1999.             MUIA_Family_Child, data->GUI.MI_REPLY = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MReply), MUIA_Menuitem_Shortcut,"R", MUIA_UserData,MMEN_REPLY, End,
  2000.             MUIA_Family_Child, data->GUI.MI_FORWARD = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MForward), MUIA_Menuitem_Shortcut,"W", MUIA_UserData,MMEN_FORWARD, End,
  2001.             MUIA_Family_Child, data->GUI.MI_BOUNCE = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MBounce), MUIA_Menuitem_Shortcut,"B", MUIA_UserData,MMEN_BOUNCE, End,
  2002.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,NM_BARLABEL, End,
  2003.             MUIA_Family_Child, data->GUI.MI_GETADDRESS = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MGetAddress), MUIA_Menuitem_Shortcut,"J", MUIA_UserData,MMEN_SAVEADDR, End,
  2004.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_Select),
  2005.                MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_SelectAll), MUIA_Menuitem_Shortcut,"L", MUIA_UserData,MMEN_SELALL, End,
  2006.                MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_SelectNone), MUIA_UserData,MMEN_SELNONE, End,
  2007.                MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_SelectToggle), MUIA_UserData,MMEN_SELTOGG, End,
  2008.             End,
  2009.             MUIA_Family_Child, data->GUI.MI_STATUS = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_SetStatus),
  2010.                MUIA_Family_Child, data->GUI.MI_TOUNREAD = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_ToUnread), MUIA_Menuitem_Shortcut,"[", MUIA_UserData,MMEN_TOUNREAD, End,
  2011.                MUIA_Family_Child, data->GUI.MI_TOREAD = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_ToRead), MUIA_Menuitem_Shortcut,"]", MUIA_UserData,MMEN_TOREAD, End,
  2012.                MUIA_Family_Child, data->GUI.MI_TOHOLD = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_ToHold), MUIA_Menuitem_Shortcut,"{", MUIA_UserData,MMEN_TOHOLD, End,
  2013.                MUIA_Family_Child, data->GUI.MI_TOQUEUED = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_ToQueued), MUIA_Menuitem_Shortcut,"}", MUIA_UserData,MMEN_TOQUEUED, End,
  2014.             End,
  2015.             MUIA_Family_Child, data->GUI.MI_CHSUBJ = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_ChangeSubj), MUIA_UserData,MMEN_CHSUBJ, End,
  2016.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,NM_BARLABEL, End,
  2017.             MUIA_Family_Child, data->GUI.MI_SEND = MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MSend), MUIA_UserData,MMEN_SEND, End,
  2018.          End,
  2019.          MUIA_Family_Child, MenuObject, MUIA_Menu_Title, GetStr(MSG_MA_Settings),
  2020.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MAddrBook),MUIA_Menuitem_Shortcut,"A",  MUIA_UserData,MMEN_ABOOK, End,
  2021.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MConfig), MUIA_Menuitem_Shortcut,"K", MUIA_UserData,MMEN_CONFIG, End,
  2022.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,GetStr(MSG_MA_MUsers), MUIA_UserData,MMEN_USER, End,
  2023.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title,"MUI...", MUIA_UserData,MMEN_MUI, End,
  2024.          End,
  2025.       End,
  2026.       data->GUI.WI = NewObject(CL_MainWin->mcc_Class,NULL,
  2027.          MUIA_Window_Title, data->WinTitle,
  2028.          MUIA_HelpNode, "MA_W",
  2029.          MUIA_Window_ID, MAKE_ID('M','A','I','N'),
  2030.          MUIA_Window_Menustrip, data->GUI.MS_MAIN,
  2031.          WindowContents, VGroup,
  2032.             Child, (C->HideGUIElements & HIDE_TBAR) ?
  2033.                VSpace(1) :
  2034.                (HGroupV,
  2035.                   MUIA_HelpNode, "MA02",
  2036.                   Child, data->GUI.TO_TOOLBAR = ToolbarObject,
  2037.                      MUIA_Toolbar_ImageType,      MUIV_Toolbar_ImageType_File,
  2038.                      MUIA_Toolbar_ImageNormal,    "PROGDIR:Icons/Main.toolbar",
  2039.                      MUIA_Toolbar_ImageGhost,     "PROGDIR:Icons/Main_G.toolbar",
  2040.                      MUIA_Toolbar_ImageSelect,    "PROGDIR:Icons/Main_S.toolbar",
  2041.                      MUIA_Toolbar_Description,    data->GUI.TB_TOOLBAR,
  2042.                      MUIA_Toolbar_ParseUnderscore,TRUE,
  2043.                      MUIA_Font,                   MUIV_Font_Tiny,
  2044.                      MUIA_ShortHelp, TRUE,
  2045.                   End,
  2046.                   Child, HSpace(0),
  2047.                End),
  2048.             Child, HGroup,
  2049.                MUIA_ShowMe, FALSE,
  2050.                Child, data->GUI.BC_STAT[ 0] = MakeStatusFlag("status_unread"),
  2051.                Child, data->GUI.BC_STAT[ 1] = MakeStatusFlag("status_old"),
  2052.                Child, data->GUI.BC_STAT[ 2] = MakeStatusFlag("status_forward"),
  2053.                Child, data->GUI.BC_STAT[ 3] = MakeStatusFlag("status_reply"),
  2054.                Child, data->GUI.BC_STAT[ 4] = MakeStatusFlag("status_waitsend"),
  2055.                Child, data->GUI.BC_STAT[ 5] = MakeStatusFlag("status_error"),
  2056.                Child, data->GUI.BC_STAT[ 6] = MakeStatusFlag("status_hold"),
  2057.                Child, data->GUI.BC_STAT[ 7] = MakeStatusFlag("status_sent"),
  2058.                Child, data->GUI.BC_STAT[ 8] = MakeStatusFlag("status_new"),
  2059.                Child, data->GUI.BC_STAT[ 9] = MakeStatusFlag("status_delete"),
  2060.                Child, data->GUI.BC_STAT[10] = MakeStatusFlag("status_download"),
  2061.                Child, data->GUI.BC_STAT[11] = MakeStatusFlag("status_group"),
  2062.                Child, data->GUI.BC_STAT[12] = MakeStatusFlag("status_urgent"),
  2063.                Child, data->GUI.BC_STAT[13] = MakeStatusFlag("status_attach"),
  2064.                Child, data->GUI.BC_STAT[14] = MakeStatusFlag("status_report"),
  2065.                Child, data->GUI.BC_STAT[15] = MakeStatusFlag("status_crypt"),
  2066.                Child, data->GUI.BC_STAT[16] = MakeStatusFlag("status_signed"),
  2067.                Child, data->GUI.ST_LAYOUT = StringObject,
  2068.                   MUIA_ObjectID, MAKE_ID('S','T','L','A'),
  2069.                   MUIA_String_MaxLen, SIZE_DEFAULT,
  2070.                End,
  2071.             End,
  2072.             Child, HGroup,
  2073.                MUIA_Group_Spacing, 1,
  2074.                Child, data->GUI.LV_FOLDERS = NListviewObject,
  2075.                   MUIA_HelpNode, "MA00",
  2076.                   MUIA_CycleChain, 1,
  2077.                   MUIA_HorizWeight, 30,
  2078.                   MUIA_NListview_NList, data->GUI.NL_FOLDERS = NewObject(CL_FolderList->mcc_Class,NULL,
  2079.                      InputListFrame,
  2080.                      MUIA_NList_MinColSortable      , 0,
  2081.                      MUIA_NList_TitleClick          , TRUE,
  2082.                      MUIA_NList_DragType            , MUIV_NList_DragType_Immediate,
  2083.                      MUIA_NList_DragSortable        , TRUE,
  2084.                      MUIA_NList_CompareHook2        , &MA_LV_FCmp2Hook,
  2085.                      MUIA_NList_DisplayHook         , &MA_LV_FDspFuncHook,
  2086.                      MUIA_NList_ConstructHook       , &MA_LV_FConHook,
  2087.                      MUIA_NList_DestructHook        , &GeneralDesHook,
  2088.                      MUIA_NList_TitleSeparator      , TRUE,
  2089.                      MUIA_NList_AutoVisible         , TRUE,
  2090.                      MUIA_NList_Title               , TRUE,
  2091.                      MUIA_NList_DoubleClick         , TRUE,
  2092.                      MUIA_NList_DefaultObjectOnClick, FALSE,
  2093.                      MUIA_Font                      , C->FixedFontList ? MUIV_NList_Font_Fixed : MUIV_NList_Font,
  2094.                      MUIA_Dropable                  , TRUE,
  2095. //                     MUIA_ContextMenu               , NULL,
  2096.                      MUIA_NList_Exports             , MUIV_NList_Exports_ColWidth|MUIV_NList_Exports_ColOrder,
  2097.                      MUIA_NList_Imports             , MUIV_NList_Imports_ColWidth|MUIV_NList_Imports_ColOrder,
  2098.                      MUIA_ObjectID, MAKE_ID('N','L','0','1'),
  2099.                   End,
  2100.                End,
  2101.                Child, BalanceObject, End,
  2102.                Child, data->GUI.LV_MAILS = NListviewObject,
  2103.                   MUIA_HelpNode, "MA01",
  2104.                   MUIA_CycleChain,1,
  2105.                   MUIA_NListview_NList, data->GUI.NL_MAILS = NListObject,
  2106.                      MUIA_NList_MinColSortable, 0,
  2107.                      MUIA_NList_TitleClick    , TRUE,
  2108.                      MUIA_NList_TitleClick2   , TRUE,
  2109.                      MUIA_NList_DragType      , MUIV_NList_DragType_Default,
  2110.                      MUIA_NList_MultiSelect   , MUIV_NList_MultiSelect_Default,
  2111.                      MUIA_NList_CompareHook2  , &MA_LV_Cmp2Hook,
  2112.                      MUIA_NList_DisplayHook   , &MA_LV_DspFuncHook,
  2113.                      MUIA_NList_AutoVisible   , TRUE,
  2114.                      MUIA_NList_Title         , TRUE,
  2115.                      MUIA_NList_TitleSeparator, TRUE,
  2116.                      MUIA_NList_DefaultObjectOnClick, TRUE,
  2117.                      MUIA_Font, C->FixedFontList ? MUIV_NList_Font_Fixed : MUIV_NList_Font,
  2118. //                     MUIA_ContextMenu         , NULL,
  2119.                      MUIA_NList_Exports       , MUIV_NList_Exports_ColWidth|MUIV_NList_Exports_ColOrder,
  2120.                      MUIA_NList_Imports       , MUIV_NList_Imports_ColWidth|MUIV_NList_Imports_ColOrder,
  2121.                      MUIA_ObjectID, MAKE_ID('N','L','0','2'),
  2122.                   End,
  2123.                End,
  2124.             End,
  2125.             Child, data->GUI.GA_INFO = GaugeObject,
  2126.                GaugeFrame,
  2127.                MUIA_Gauge_Horiz   , TRUE,
  2128.                MUIA_Gauge_InfoText, " ",
  2129.                MUIA_ShowMe        , !(C->HideGUIElements & HIDE_INFO) ,
  2130.             End,
  2131.          End,
  2132.       End;
  2133.       if (data->GUI.WI)
  2134.       {
  2135.          MA_MakeFOFormat(data->GUI.NL_FOLDERS);
  2136.          MA_MakeMAFormat(data->GUI.NL_MAILS);
  2137.          DoMethod(G->App, OM_ADDMEMBER, data->GUI.WI);
  2138.          for (i = 0; i < 17; i++) DoMethod(data->GUI.NL_MAILS, MUIM_NList_UseImage, data->GUI.BC_STAT[i], i, 0);
  2139.          DoMethod(data->GUI.NL_FOLDERS, MUIM_NList_UseImage, data->GUI.BC_STAT[15], 0, 0);
  2140.          set(data->GUI.WI,MUIA_Window_DefaultObject,data->GUI.LV_MAILS);
  2141.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_ABOUT     ,G->AY_Win,3,MUIM_Set                ,MUIA_Window_Open,TRUE);
  2142.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_VERSION   ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_CheckVersionHook);
  2143.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_ERRORS    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ShowErrorsHook);
  2144.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_LOGIN     ,MUIV_Notify_Application  ,2,MUIM_Application_ReturnID,ID_RESTART);
  2145.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_HIDE      ,MUIV_Notify_Application  ,3,MUIM_Set                 ,MUIA_Application_Iconified,TRUE);
  2146.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_QUIT      ,MUIV_Notify_Application  ,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
  2147.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_NEWF      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&FO_NewFolderHook);
  2148.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_NEWS      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&FO_NewSeparatorHook);
  2149.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_EDITF     ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&FO_EditFolderHook);
  2150.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_DELETEF   ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&FO_DeleteFolderHook);
  2151.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_OSAVE     ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&FO_SetOrderHook,SO_SAVE);
  2152.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_ORESET    ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&FO_SetOrderHook,SO_RESET);
  2153.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SELALL    ,data->GUI.NL_MAILS,4,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_On,NULL);
  2154.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SELNONE   ,data->GUI.NL_MAILS,4,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_Off,NULL);
  2155.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SELTOGG   ,data->GUI.NL_MAILS,4,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_Toggle,NULL);
  2156.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SEARCH    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&FI_OpenHook);
  2157.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_FILTER    ,MUIV_Notify_Application  ,5,MUIM_CallHook            ,&MA_ApplyRulesHook,APPLY_USER,0,FALSE);
  2158.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_DELDEL    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_DeleteDeletedHook);
  2159.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_INDEX     ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_RescanIndexHook);
  2160.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_FLUSH     ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_FlushIndexHook);
  2161.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_ABOOK     ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&AB_OpenHook,ABM_EDIT);
  2162.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_EXPORT    ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_ExportMessagesHook,TRUE);
  2163.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_IMPORT    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ImportMessagesHook);
  2164.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_GETMAIL   ,MUIV_Notify_Application  ,6,MUIM_CallHook            ,&MA_PopNowHook,POP_USER,-1,0,FALSE);
  2165.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SENDMAIL  ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SendHook,SEND_ALL);
  2166.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_EXMAIL    ,MUIV_Notify_Application  ,6,MUIM_CallHook            ,&MA_PopNowHook,POP_USER,-1,IEQUALIFIER_LSHIFT,FALSE);
  2167.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_READ      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ReadMessageHook);
  2168.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_EDIT      ,MUIV_Notify_Application  ,5,MUIM_CallHook            ,&MA_NewMessageHook,NEW_EDIT,0,FALSE);
  2169.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_MOVE      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_MoveMessageHook);
  2170.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_COPY      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_CopyMessageHook);
  2171.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_DELETE    ,MUIV_Notify_Application  ,4,MUIM_CallHook            ,&MA_DeleteMessageHook,0,FALSE);
  2172.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_PRINT     ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SavePrintHook,TRUE);
  2173.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SAVE      ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SavePrintHook,FALSE);
  2174.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_DETACH    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_SaveAttachHook);
  2175.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_CROP      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_RemoveAttachHook);
  2176.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_EXPMSG    ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_ExportMessagesHook,FALSE);
  2177.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_NEW       ,MUIV_Notify_Application  ,5,MUIM_CallHook            ,&MA_NewMessageHook,NEW_NEW,0,FALSE);
  2178.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_REPLY     ,MUIV_Notify_Application  ,5,MUIM_CallHook            ,&MA_NewMessageHook,NEW_REPLY,0,FALSE);
  2179.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_FORWARD   ,MUIV_Notify_Application  ,5,MUIM_CallHook            ,&MA_NewMessageHook,NEW_FORWARD,0,FALSE);
  2180.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_BOUNCE    ,MUIV_Notify_Application  ,5,MUIM_CallHook            ,&MA_NewMessageHook,NEW_BOUNCE,0,FALSE);
  2181.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SAVEADDR  ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_GetAddressHook);
  2182.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_CHSUBJ    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ChangeSubjectHook);
  2183.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SEND      ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SendHook,SEND_ACTIVE);
  2184.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_TOREAD    ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SetStatusToHook,STATUS_OLD);
  2185.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_TOUNREAD  ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SetStatusToHook,STATUS_UNR);
  2186.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_TOHOLD    ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SetStatusToHook,STATUS_HLD);
  2187.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_TOQUEUED  ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SetStatusToHook,STATUS_WFS);
  2188.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_CONFIG    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&CO_OpenHook);
  2189.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_USER      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&US_OpenHook);
  2190.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_MUI       ,MUIV_Notify_Application  ,2,MUIM_Application_OpenConfigWindow,0);
  2191.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_ABOUTMUI  ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_AboutMUIHook);
  2192.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SCRIPT    ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_CallRexxHook,-1);
  2193.          for (i = 0; i < 10; i++) DoMethod(data->GUI.WI,MUIM_Notify,MUIA_Window_MenuAction,MMEN_MACRO+i,MUIV_Notify_Application,3,MUIM_CallHook        ,&MA_CallRexxHook, i);
  2194.          for (i = 0; i < MAXP3; i++) DoMethod(data->GUI.WI,MUIM_Notify,MUIA_Window_MenuAction,MMEN_POPHOST+i,MUIV_Notify_Application,6,MUIM_CallHook   ,&MA_PopNowHook,POP_USER,i,0,FALSE);
  2195.          if (data->GUI.TO_TOOLBAR)
  2196.          {
  2197.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 0, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,2,MUIM_CallHook,&MA_ReadMessageHook);
  2198.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 1, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,5,MUIM_CallHook,&MA_NewMessageHook,NEW_EDIT,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2199.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 2, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,2,MUIM_CallHook,&MA_MoveMessageHook);
  2200.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 3, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,4,MUIM_CallHook,&MA_DeleteMessageHook,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2201.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 4, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,2,MUIM_CallHook,&MA_GetAddressHook);
  2202.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 6, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,5,MUIM_CallHook,&MA_NewMessageHook,NEW_NEW,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2203.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 7, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,5,MUIM_CallHook,&MA_NewMessageHook,NEW_REPLY,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2204.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 8, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,5,MUIM_CallHook,&MA_NewMessageHook,NEW_FORWARD,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2205.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify,10, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,9,MUIM_Application_PushMethod,G->App,6,MUIM_CallHook,&MA_PopNowHook,POP_USER,-1,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2206.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify,11, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,7,MUIM_Application_PushMethod,G->App,3,MUIM_CallHook,&MA_SendHook,SEND_ALL);
  2207.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify,13, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,5,MUIM_CallHook,&MA_ApplyRulesHook,APPLY_USER,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2208.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify,14, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,2,MUIM_CallHook,&FI_OpenHook);
  2209.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify,15, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,3,MUIM_CallHook,&AB_OpenHook,ABM_EDIT);
  2210.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify,16, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,2,MUIM_CallHook,&CO_OpenHook);
  2211.          }
  2212.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_DoubleClick   ,MUIV_EveryTime,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_ReadMessageHook,FALSE);
  2213.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_TitleClick    ,MUIV_EveryTime,MUIV_Notify_Self         ,4,MUIM_NList_Sort3         ,MUIV_TriggerValue,MUIV_NList_SortTypeAdd_2Values,MUIV_NList_Sort3_SortType_Both);
  2214.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_TitleClick2   ,MUIV_EveryTime,MUIV_Notify_Self         ,4,MUIM_NList_Sort3         ,MUIV_TriggerValue,MUIV_NList_SortTypeAdd_2Values,MUIV_NList_Sort3_SortType_2);
  2215.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_SortType      ,MUIV_EveryTime,MUIV_Notify_Self         ,3,MUIM_Set                 ,MUIA_NList_TitleMark,MUIV_TriggerValue);
  2216.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_SortType2     ,MUIV_EveryTime,MUIV_Notify_Self         ,3,MUIM_Set                 ,MUIA_NList_TitleMark2,MUIV_TriggerValue);
  2217.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_SelectChange  ,TRUE          ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ChangeSelectedHook);
  2218.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_Active        ,MUIV_EveryTime,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ChangeSelectedHook);
  2219.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_Active        ,MUIV_EveryTime,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_SetMessageInfoHook);
  2220.          DoMethod(data->GUI.NL_FOLDERS     ,MUIM_Notify,MUIA_NList_DoubleClick   ,MUIV_EveryTime,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&FO_EditFolderHook);
  2221.          DoMethod(data->GUI.NL_FOLDERS     ,MUIM_Notify,MUIA_NList_TitleClick    ,MUIV_EveryTime,MUIV_Notify_Self         ,3,MUIM_NList_Sort2         ,MUIV_TriggerValue,MUIV_NList_SortTypeAdd_2Values);
  2222.          DoMethod(data->GUI.NL_FOLDERS     ,MUIM_Notify,MUIA_NList_SortType      ,MUIV_EveryTime,MUIV_Notify_Self         ,3,MUIM_Set                 ,MUIA_NList_TitleMark,MUIV_TriggerValue);
  2223.          DoMethod(data->GUI.NL_FOLDERS     ,MUIM_Notify,MUIA_NList_Active        ,MUIV_EveryTime,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ChangeFolderHook);
  2224.          DoMethod(data->GUI.NL_FOLDERS     ,MUIM_Notify,MUIA_NList_Active        ,MUIV_EveryTime,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_SetFolderInfoHook);
  2225.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_CloseRequest ,TRUE          ,MUIV_Notify_Application  ,2,MUIM_Application_ReturnID,ID_CLOSEALL);
  2226.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_InputEvent   ,"-repeat del" ,MUIV_Notify_Application  ,4,MUIM_CallHook            ,&MA_DelKeyHook,FALSE);
  2227.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_InputEvent   ,"-repeat shift del" ,MUIV_Notify_Application  ,4,MUIM_CallHook      ,&MA_DelKeyHook,TRUE);
  2228.          DoMethod(G->App                   ,MUIM_Notify,MUIA_Application_Iconified,FALSE        ,data->GUI.WI             ,3,MUIM_Set                 ,MUIA_Window_Open,TRUE);
  2229.          for (i = 0; i < 10; i++)
  2230.          {
  2231.             key[8] = '0'+i;
  2232.             DoMethod(data->GUI.WI, MUIM_Notify,MUIA_Window_InputEvent, key, data->GUI.NL_FOLDERS, 3, MUIM_Set, MUIA_NList_Active, i);
  2233.          }
  2234.          return data;
  2235.       }
  2236.       free(data);
  2237.    }
  2238.    return NULL;
  2239. }
  2240. ///
  2241.  
  2242.